diff options
310 files changed, 17034 insertions, 6802 deletions
@@ -266,6 +266,7 @@ cc_library( "src/google/protobuf/compiler/java/java_enum_field_lite.cc", "src/google/protobuf/compiler/java/java_enum_lite.cc", "src/google/protobuf/compiler/java/java_extension.cc", + "src/google/protobuf/compiler/java/java_extension_lite.cc", "src/google/protobuf/compiler/java/java_field.cc", "src/google/protobuf/compiler/java/java_file.cc", "src/google/protobuf/compiler/java/java_generator.cc", @@ -376,6 +377,8 @@ RELATIVE_TEST_PROTOS = [ "google/protobuf/unittest_preserve_unknown_enum.proto", "google/protobuf/unittest_preserve_unknown_enum2.proto", "google/protobuf/unittest_proto3_arena.proto", + "google/protobuf/unittest_proto3_arena_lite.proto", + "google/protobuf/unittest_proto3_lite.proto", "google/protobuf/unittest_well_known_types.proto", "google/protobuf/util/internal/testdata/anys.proto", "google/protobuf/util/internal/testdata/books.proto", @@ -436,6 +439,7 @@ cc_test( "src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc", "src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc", "src/google/protobuf/compiler/cpp/cpp_unittest.cc", + "src/google/protobuf/compiler/cpp/metadata_test.cc", "src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc", "src/google/protobuf/compiler/importer_unittest.cc", "src/google/protobuf/compiler/java/java_doc_comment_unittest.cc", @@ -460,7 +464,9 @@ cc_test( "src/google/protobuf/message_unittest.cc", "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/reflection_ops_unittest.cc", "src/google/protobuf/repeated_field_reflection_unittest.cc", "src/google/protobuf/repeated_field_unittest.cc", @@ -535,9 +541,9 @@ java_library( "java/util/src/main/java/com/google/protobuf/util/*.java", ]), deps = [ - "protobuf_java", - "//external:gson", - "//external:guava", + "protobuf_java", + "//external:gson", + "//external:guava", ], visibility = ["//visibility:public"], ) @@ -558,6 +564,7 @@ py_library( "python/google/protobuf/internal/test_util.py", ], ), + srcs_version = "PY2AND3", imports = ["python"], ) @@ -642,6 +649,7 @@ py_proto_library( include = "src", default_runtime = "", protoc = ":protoc", + srcs_version = "PY2AND3", deps = [":protobuf_python"], ) @@ -654,6 +662,7 @@ py_proto_library( include = "python", default_runtime = ":protobuf_python", protoc = ":protoc", + srcs_version = "PY2AND3", deps = [":python_common_test_protos"], ) diff --git a/Makefile.am b/Makefile.am index cadc7d8d..3e988816 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,7 +9,7 @@ AUTOMAKE_OPTIONS = foreign SUBDIRS = . src # Always include gmock in distributions. -DIST_SUBDIRS = $(subdirs) src conformance +DIST_SUBDIRS = $(subdirs) src conformance benchmarks # 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, @@ -36,6 +36,10 @@ clean-local: echo "Making clean in conformance"; \ cd conformance && $(MAKE) $(AM_MAKEFLAGS) clean; \ fi; \ + if test -e benchmarks/Makefile; then \ + echo "Making clean in benchmarks"; \ + cd benchmarks && $(MAKE) $(AM_MAKEFLAGS) clean; \ + fi; \ if test -e objectivec/DevTools; then \ echo "Cleaning any ObjC pyc files"; \ rm -f objectivec/DevTools/*.pyc; \ @@ -154,6 +158,7 @@ csharp_EXTRA_DIST= \ csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs \ csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs \ 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 \ diff --git a/benchmarks/Makefile.am b/benchmarks/Makefile.am new file mode 100644 index 00000000..1e162eb1 --- /dev/null +++ b/benchmarks/Makefile.am @@ -0,0 +1,66 @@ + +benchmarks_protoc_inputs = \ + benchmarks.proto \ + benchmark_messages_proto3.proto + +benchmarks_protoc_inputs_proto2 = \ + benchmark_messages_proto2.proto + +benchmarks_protoc_outputs = \ + benchmarks.pb.cc \ + benchmarks.pb.h \ + benchmark_messages_proto3.pb.cc \ + benchmark_messages_proto3.pb.h + +benchmarks_protoc_outputs_proto2 = \ + benchmark_messages_proto2.pb.cc \ + benchmark_messages_proto2.pb.h + +bin_PROGRAMS = generate-datasets + +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) + +# 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 + +$(benchmarks_protoc_outputs): protoc_middleman +$(benchmarks_protoc_outputs_proto2): protoc_middleman2 + +CLEANFILES = \ + $(benchmarks_protoc_outputs) \ + $(benchmarks_protoc_outputs_proto2) \ + protoc_middleman \ + protoc_middleman2 \ + dataset.* + +if USE_EXTERNAL_PROTOC + +protoc_middleman: $(benchmarks_protoc_inputs) + $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. $(benchmarks_protoc_inputs) + touch protoc_middleman + +protoc_middleman2: $(benchmarks_protoc_inputs_proto2) + $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. $(benchmarks_protoc_inputs_proto2) + touch protoc_middleman2 + +else + +# 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 + +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 + +endif diff --git a/benchmarks/README.md b/benchmarks/README.md new file mode 100644 index 00000000..c9027805 --- /dev/null +++ b/benchmarks/README.md @@ -0,0 +1,28 @@ + +# Protocol Buffers Benchmarks + +This directory contains benchmarking schemas and data sets that you +can use to test a variety of performance scenarios against your +protobuf language runtime. + +The schema for the datasets is described in `benchmarks.proto`. + +Generate the data sets like so: + +``` +$ make +$ ./generate-datasets +Wrote dataset: dataset.google_message1_proto3.pb +Wrote dataset: dataset.google_message1_proto2.pb +Wrote dataset: dataset.google_message2.pb +$ +``` + +Each data set will be written to its own file. Benchmarks will +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 +that make the overall suite diverse without being too large or having +too many similar tests. Ideally everyone can run through the entire +suite without the test run getting too long. diff --git a/benchmarks/google_speed.proto b/benchmarks/benchmark_messages_proto2.proto index 16f6d678..01f67a1a 100644 --- a/benchmarks/google_speed.proto +++ b/benchmarks/benchmark_messages_proto2.proto @@ -1,11 +1,14 @@ +// Benchmark messages for proto2. + syntax = "proto2"; -package benchmarks; +package benchmarks.proto2; +option java_package = "com.google.protobuf.benchmarks"; -option java_outer_classname = "GoogleSpeed"; +// This is the default, but we specify it here explicitly. option optimize_for = SPEED; -message SpeedMessage1 { +message GoogleMessage1 { required string field1 = 1; optional string field9 = 9; optional string field18 = 18; @@ -40,7 +43,7 @@ message SpeedMessage1 { optional int32 field23 = 23 [default=0]; optional bool field24 = 24 [default=false]; optional int32 field25 = 25 [default=0]; - optional SpeedMessage1SubMessage field15 = 15; + optional GoogleMessage1SubMessage field15 = 15; optional bool field78 = 78; optional int32 field67 = 67 [default=0]; optional int32 field68 = 68; @@ -49,7 +52,7 @@ message SpeedMessage1 { optional int32 field131 = 131 [default=0]; } -message SpeedMessage1SubMessage { +message GoogleMessage1SubMessage { optional int32 field1 = 1 [default=0]; optional int32 field2 = 2 [default=0]; optional int32 field3 = 3 [default=0]; @@ -72,7 +75,7 @@ message SpeedMessage1SubMessage { optional uint64 field300 = 300; } -message SpeedMessage2 { +message GoogleMessage2 { optional string field1 = 1; optional int64 field3 = 3; optional int64 field4 = 4; @@ -112,7 +115,7 @@ message SpeedMessage2 { repeated int32 field73 = 73; optional int32 field20 = 20 [default=0]; optional string field24 = 24; - optional SpeedMessage2GroupedMessage field31 = 31; + optional GoogleMessage2GroupedMessage field31 = 31; } repeated string field128 = 128; optional int64 field131 = 131; @@ -123,7 +126,7 @@ message SpeedMessage2 { optional bool field206 = 206 [default=false]; } -message SpeedMessage2GroupedMessage { +message GoogleMessage2GroupedMessage { optional float field1 = 1; optional float field2 = 2; optional float field3 = 3 [default=0.0]; diff --git a/benchmarks/benchmark_messages_proto3.proto b/benchmarks/benchmark_messages_proto3.proto new file mode 100644 index 00000000..32f58698 --- /dev/null +++ b/benchmarks/benchmark_messages_proto3.proto @@ -0,0 +1,76 @@ +// 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; + +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/benchmarks.proto b/benchmarks/benchmarks.proto new file mode 100644 index 00000000..51c0b548 --- /dev/null +++ b/benchmarks/benchmarks.proto @@ -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. + +syntax = "proto3"; +package benchmarks; +option java_package = "com.google.protobuf.benchmarks"; + +message BenchmarkDataset { + // Name of the benchmark dataset. This should be unique across all datasets. + // Should only contain word characters: [a-zA-Z0-9_] + string name = 1; + + // 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. + string message_name = 2; + + // 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. + repeated bytes payload = 3; +} diff --git a/benchmarks/generate_datasets.cc b/benchmarks/generate_datasets.cc new file mode 100644 index 00000000..61e7adf1 --- /dev/null +++ b/benchmarks/generate_datasets.cc @@ -0,0 +1,117 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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 <fstream> +#include <iostream> +#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<std::string> 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<std::string>& 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<std::string> 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<char>(file)), + std::istreambuf_iterator<char>()); +} + +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/cmake/extract_includes.bat.in b/cmake/extract_includes.bat.in index c76973c9..b593e0c9 100644 --- a/cmake/extract_includes.bat.in +++ b/cmake/extract_includes.bat.in @@ -23,7 +23,6 @@ copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\command_line_ copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\cpp_generator.h include\google\protobuf\compiler\cpp\cpp_generator.h copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_generator.h include\google\protobuf\compiler\csharp\csharp_generator.h copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_names.h include\google\protobuf\compiler\csharp\csharp_names.h -copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_options.h include\google\protobuf\compiler\csharp\csharp_options.h 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 diff --git a/cmake/tests.cmake b/cmake/tests.cmake index 941f33d8..76fdf8ef 100644 --- a/cmake/tests.cmake +++ b/cmake/tests.cmake @@ -52,6 +52,8 @@ set(tests_protos google/protobuf/unittest_preserve_unknown_enum.proto google/protobuf/unittest_preserve_unknown_enum2.proto google/protobuf/unittest_proto3_arena.proto + google/protobuf/unittest_proto3_arena_lite.proto + google/protobuf/unittest_proto3_lite.proto google/protobuf/unittest_well_known_types.proto google/protobuf/util/internal/testdata/anys.proto google/protobuf/util/internal/testdata/books.proto @@ -116,6 +118,7 @@ set(tests_files ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_bootstrap_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/metadata_test.cc ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc ${protobuf_source_dir}/src/google/protobuf/compiler/importer_unittest.cc ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc @@ -140,7 +143,9 @@ set(tests_files ${protobuf_source_dir}/src/google/protobuf/message_unittest.cc ${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/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 diff --git a/configure.ac b/configure.ac index 33a6c64d..d56a7047 100644 --- a/configure.ac +++ b/configure.ac @@ -180,5 +180,5 @@ export CFLAGS export CXXFLAGS AC_CONFIG_SUBDIRS([gmock]) -AC_CONFIG_FILES([Makefile src/Makefile conformance/Makefile protobuf.pc protobuf-lite.pc]) +AC_CONFIG_FILES([Makefile src/Makefile benchmarks/Makefile conformance/Makefile protobuf.pc protobuf-lite.pc]) AC_OUTPUT diff --git a/conformance/failure_list_ruby.txt b/conformance/failure_list_ruby.txt index ade0ff4c..7c12da06 100644 --- a/conformance/failure_list_ruby.txt +++ b/conformance/failure_list_ruby.txt @@ -80,7 +80,6 @@ JsonInput.Int32FieldMaxFloatValue.JsonOutput JsonInput.Int32FieldMaxFloatValue.ProtobufOutput JsonInput.Int32FieldMinFloatValue.JsonOutput JsonInput.Int32FieldMinFloatValue.ProtobufOutput -JsonInput.Int32FieldMinValue.JsonOutput JsonInput.Int32FieldStringValue.JsonOutput JsonInput.Int32FieldStringValue.ProtobufOutput JsonInput.Int32FieldStringValueEscaped.JsonOutput @@ -125,7 +124,6 @@ JsonInput.OptionalUint64Wrapper.ProtobufOutput JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput JsonInput.OriginalProtoFieldName.JsonOutput -JsonInput.OriginalProtoFieldName.ProtobufOutput JsonInput.PrimitiveRepeatedField.JsonOutput JsonInput.PrimitiveRepeatedField.ProtobufOutput JsonInput.RepeatedBoolWrapper.JsonOutput diff --git a/csharp/src/AddressBook/AddPerson.cs b/csharp/src/AddressBook/AddPerson.cs index 6eeb9f6e..62d1788d 100644 --- a/csharp/src/AddressBook/AddPerson.cs +++ b/csharp/src/AddressBook/AddPerson.cs @@ -73,13 +73,13 @@ namespace Google.Protobuf.Examples.AddressBook switch (type)
{
case "mobile":
- phoneNumber.Type = Person.Types.PhoneType.MOBILE;
+ phoneNumber.Type = Person.Types.PhoneType.Mobile;
break;
case "home":
- phoneNumber.Type = Person.Types.PhoneType.HOME;
+ phoneNumber.Type = Person.Types.PhoneType.Home;
break;
case "work":
- phoneNumber.Type = Person.Types.PhoneType.WORK;
+ phoneNumber.Type = Person.Types.PhoneType.Work;
break;
default:
output.Write("Unknown phone type. Using default.");
diff --git a/csharp/src/AddressBook/Addressbook.cs b/csharp/src/AddressBook/Addressbook.cs index 166dd49a..362e1cb6 100644 --- a/csharp/src/AddressBook/Addressbook.cs +++ b/csharp/src/AddressBook/Addressbook.cs @@ -228,9 +228,9 @@ namespace Google.Protobuf.Examples.AddressBook { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Types { public enum PhoneType { - MOBILE = 0, - HOME = 1, - WORK = 2, + [pbr::OriginalName("MOBILE")] Mobile = 0, + [pbr::OriginalName("HOME")] Home = 1, + [pbr::OriginalName("WORK")] Work = 2, } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] @@ -273,7 +273,7 @@ namespace Google.Protobuf.Examples.AddressBook { /// <summary>Field number for the "type" field.</summary> public const int TypeFieldNumber = 2; - private global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType type_ = global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.MOBILE; + private global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType type_ = 0; public global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType Type { get { return type_; } set { @@ -300,7 +300,7 @@ namespace Google.Protobuf.Examples.AddressBook { public override int GetHashCode() { int hash = 1; if (Number.Length != 0) hash ^= Number.GetHashCode(); - if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.MOBILE) hash ^= Type.GetHashCode(); + if (Type != 0) hash ^= Type.GetHashCode(); return hash; } @@ -313,7 +313,7 @@ namespace Google.Protobuf.Examples.AddressBook { output.WriteRawTag(10); output.WriteString(Number); } - if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.MOBILE) { + if (Type != 0) { output.WriteRawTag(16); output.WriteEnum((int) Type); } @@ -324,7 +324,7 @@ namespace Google.Protobuf.Examples.AddressBook { if (Number.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Number); } - if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.MOBILE) { + if (Type != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); } return size; @@ -337,7 +337,7 @@ namespace Google.Protobuf.Examples.AddressBook { if (other.Number.Length != 0) { Number = other.Number; } - if (other.Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.MOBILE) { + if (other.Type != 0) { Type = other.Type; } } diff --git a/csharp/src/AddressBook/ListPeople.cs b/csharp/src/AddressBook/ListPeople.cs index 3979430f..3758c1bc 100644 --- a/csharp/src/AddressBook/ListPeople.cs +++ b/csharp/src/AddressBook/ListPeople.cs @@ -55,13 +55,13 @@ namespace Google.Protobuf.Examples.AddressBook {
switch (phoneNumber.Type)
{
- case Person.Types.PhoneType.MOBILE:
+ case Person.Types.PhoneType.Mobile:
Console.Write(" Mobile phone #: ");
break;
- case Person.Types.PhoneType.HOME:
+ case Person.Types.PhoneType.Home:
Console.Write(" Home phone #: ");
break;
- case Person.Types.PhoneType.WORK:
+ case Person.Types.PhoneType.Work:
Console.Write(" Work phone #: ");
break;
}
diff --git a/csharp/src/Google.Protobuf.Conformance/Conformance.cs b/csharp/src/Google.Protobuf.Conformance/Conformance.cs index 7d85d28c..1674a673 100644 --- a/csharp/src/Google.Protobuf.Conformance/Conformance.cs +++ b/csharp/src/Google.Protobuf.Conformance/Conformance.cs @@ -199,15 +199,15 @@ namespace Conformance { } #region Enums public enum WireFormat { - UNSPECIFIED = 0, - PROTOBUF = 1, - JSON = 2, + [pbr::OriginalName("UNSPECIFIED")] Unspecified = 0, + [pbr::OriginalName("PROTOBUF")] Protobuf = 1, + [pbr::OriginalName("JSON")] Json = 2, } public enum ForeignEnum { - FOREIGN_FOO = 0, - FOREIGN_BAR = 1, - FOREIGN_BAZ = 2, + [pbr::OriginalName("FOREIGN_FOO")] ForeignFoo = 0, + [pbr::OriginalName("FOREIGN_BAR")] ForeignBar = 1, + [pbr::OriginalName("FOREIGN_BAZ")] ForeignBaz = 2, } #endregion @@ -278,7 +278,7 @@ namespace Conformance { /// <summary>Field number for the "requested_output_format" field.</summary> public const int RequestedOutputFormatFieldNumber = 3; - private global::Conformance.WireFormat requestedOutputFormat_ = global::Conformance.WireFormat.UNSPECIFIED; + private global::Conformance.WireFormat requestedOutputFormat_ = 0; /// <summary> /// Which format should the testee serialize its message to? /// </summary> @@ -328,7 +328,7 @@ namespace Conformance { int hash = 1; if (payloadCase_ == PayloadOneofCase.ProtobufPayload) hash ^= ProtobufPayload.GetHashCode(); if (payloadCase_ == PayloadOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode(); - if (RequestedOutputFormat != global::Conformance.WireFormat.UNSPECIFIED) hash ^= RequestedOutputFormat.GetHashCode(); + if (RequestedOutputFormat != 0) hash ^= RequestedOutputFormat.GetHashCode(); hash ^= (int) payloadCase_; return hash; } @@ -346,7 +346,7 @@ namespace Conformance { output.WriteRawTag(18); output.WriteString(JsonPayload); } - if (RequestedOutputFormat != global::Conformance.WireFormat.UNSPECIFIED) { + if (RequestedOutputFormat != 0) { output.WriteRawTag(24); output.WriteEnum((int) RequestedOutputFormat); } @@ -360,7 +360,7 @@ namespace Conformance { if (payloadCase_ == PayloadOneofCase.JsonPayload) { size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonPayload); } - if (RequestedOutputFormat != global::Conformance.WireFormat.UNSPECIFIED) { + if (RequestedOutputFormat != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) RequestedOutputFormat); } return size; @@ -370,7 +370,7 @@ namespace Conformance { if (other == null) { return; } - if (other.RequestedOutputFormat != global::Conformance.WireFormat.UNSPECIFIED) { + if (other.RequestedOutputFormat != 0) { RequestedOutputFormat = other.RequestedOutputFormat; } switch (other.PayloadCase) { @@ -1044,7 +1044,7 @@ namespace Conformance { /// <summary>Field number for the "optional_nested_enum" field.</summary> public const int OptionalNestedEnumFieldNumber = 21; - private global::Conformance.TestAllTypes.Types.NestedEnum optionalNestedEnum_ = global::Conformance.TestAllTypes.Types.NestedEnum.FOO; + private global::Conformance.TestAllTypes.Types.NestedEnum optionalNestedEnum_ = 0; public global::Conformance.TestAllTypes.Types.NestedEnum OptionalNestedEnum { get { return optionalNestedEnum_; } set { @@ -1054,7 +1054,7 @@ namespace Conformance { /// <summary>Field number for the "optional_foreign_enum" field.</summary> public const int OptionalForeignEnumFieldNumber = 22; - private global::Conformance.ForeignEnum optionalForeignEnum_ = global::Conformance.ForeignEnum.FOREIGN_FOO; + private global::Conformance.ForeignEnum optionalForeignEnum_ = 0; public global::Conformance.ForeignEnum OptionalForeignEnum { get { return optionalForeignEnum_; } set { @@ -2079,8 +2079,8 @@ namespace Conformance { if (OptionalBytes.Length != 0) hash ^= OptionalBytes.GetHashCode(); if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode(); if (optionalForeignMessage_ != null) hash ^= OptionalForeignMessage.GetHashCode(); - if (OptionalNestedEnum != global::Conformance.TestAllTypes.Types.NestedEnum.FOO) hash ^= OptionalNestedEnum.GetHashCode(); - if (OptionalForeignEnum != global::Conformance.ForeignEnum.FOREIGN_FOO) hash ^= OptionalForeignEnum.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(); @@ -2247,11 +2247,11 @@ namespace Conformance { output.WriteRawTag(154, 1); output.WriteMessage(OptionalForeignMessage); } - if (OptionalNestedEnum != global::Conformance.TestAllTypes.Types.NestedEnum.FOO) { + if (OptionalNestedEnum != 0) { output.WriteRawTag(168, 1); output.WriteEnum((int) OptionalNestedEnum); } - if (OptionalForeignEnum != global::Conformance.ForeignEnum.FOREIGN_FOO) { + if (OptionalForeignEnum != 0) { output.WriteRawTag(176, 1); output.WriteEnum((int) OptionalForeignEnum); } @@ -2492,10 +2492,10 @@ namespace Conformance { if (optionalForeignMessage_ != null) { size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalForeignMessage); } - if (OptionalNestedEnum != global::Conformance.TestAllTypes.Types.NestedEnum.FOO) { + if (OptionalNestedEnum != 0) { size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalNestedEnum); } - if (OptionalForeignEnum != global::Conformance.ForeignEnum.FOREIGN_FOO) { + if (OptionalForeignEnum != 0) { size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalForeignEnum); } if (OptionalStringPiece.Length != 0) { @@ -2719,10 +2719,10 @@ namespace Conformance { } OptionalForeignMessage.MergeFrom(other.OptionalForeignMessage); } - if (other.OptionalNestedEnum != global::Conformance.TestAllTypes.Types.NestedEnum.FOO) { + if (other.OptionalNestedEnum != 0) { OptionalNestedEnum = other.OptionalNestedEnum; } - if (other.OptionalForeignEnum != global::Conformance.ForeignEnum.FOREIGN_FOO) { + if (other.OptionalForeignEnum != 0) { OptionalForeignEnum = other.OptionalForeignEnum; } if (other.OptionalStringPiece.Length != 0) { @@ -3448,13 +3448,13 @@ namespace Conformance { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Types { public enum NestedEnum { - FOO = 0, - BAR = 1, - BAZ = 2, + [pbr::OriginalName("FOO")] Foo = 0, + [pbr::OriginalName("BAR")] Bar = 1, + [pbr::OriginalName("BAZ")] Baz = 2, /// <summary> /// Intentionally negative. /// </summary> - NEG = -1, + [pbr::OriginalName("NEG")] Neg = -1, } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] diff --git a/csharp/src/Google.Protobuf.Conformance/Program.cs b/csharp/src/Google.Protobuf.Conformance/Program.cs index f3f7e295..19827c48 100644 --- a/csharp/src/Google.Protobuf.Conformance/Program.cs +++ b/csharp/src/Google.Protobuf.Conformance/Program.cs @@ -109,10 +109,10 @@ namespace Google.Protobuf.Conformance { switch (request.RequestedOutputFormat) { - case global::Conformance.WireFormat.JSON: + case global::Conformance.WireFormat.Json: var formatter = new JsonFormatter(new JsonFormatter.Settings(false, typeRegistry)); return new ConformanceResponse { JsonPayload = formatter.Format(message) }; - case global::Conformance.WireFormat.PROTOBUF: + case global::Conformance.WireFormat.Protobuf: return new ConformanceResponse { ProtobufPayload = message.ToByteString() }; default: throw new Exception("Unsupported request output format: " + request.PayloadCase); diff --git a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs index 38ba227f..c616470e 100644 --- a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs +++ b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs @@ -58,7 +58,7 @@ namespace Google.Protobuf new FieldCodecTestData<float>(FieldCodec.ForFloat(100), 1234.5f, "Float"), new FieldCodecTestData<double>(FieldCodec.ForDouble(100), 1234567890.5d, "Double"), new FieldCodecTestData<ForeignEnum>( - FieldCodec.ForEnum(100, t => (int) t, t => (ForeignEnum) t), ForeignEnum.FOREIGN_BAZ, "Enum"), + FieldCodec.ForEnum(100, t => (int) t, t => (ForeignEnum) t), ForeignEnum.ForeignBaz, "Enum"), new FieldCodecTestData<ForeignMessage>( FieldCodec.ForMessage(100, ForeignMessage.Parser), new ForeignMessage { C = 10 }, "Message"), }; diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs index 5c2a052b..8b153d69 100644 --- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs +++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs @@ -66,13 +66,13 @@ namespace Google.Protobuf Assert.AreEqual(0, message.SingleFixed32);
Assert.AreEqual(0L, message.SingleFixed64);
Assert.AreEqual(0.0f, message.SingleFloat);
- Assert.AreEqual(ForeignEnum.FOREIGN_UNSPECIFIED, message.SingleForeignEnum);
+ Assert.AreEqual(ForeignEnum.ForeignUnspecified, message.SingleForeignEnum);
Assert.IsNull(message.SingleForeignMessage);
- Assert.AreEqual(ImportEnum.IMPORT_ENUM_UNSPECIFIED, message.SingleImportEnum);
+ Assert.AreEqual(ImportEnum.Unspecified, message.SingleImportEnum);
Assert.IsNull(message.SingleImportMessage);
Assert.AreEqual(0, message.SingleInt32);
Assert.AreEqual(0L, message.SingleInt64);
- Assert.AreEqual(TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED, message.SingleNestedEnum);
+ Assert.AreEqual(TestAllTypes.Types.NestedEnum.Unspecified, message.SingleNestedEnum);
Assert.IsNull(message.SingleNestedMessage);
Assert.IsNull(message.SinglePublicImportMessage);
Assert.AreEqual(0, message.SingleSfixed32);
@@ -145,13 +145,13 @@ namespace Google.Protobuf SingleFixed32 = 23,
SingleFixed64 = 1234567890123,
SingleFloat = 12.25f,
- SingleForeignEnum = ForeignEnum.FOREIGN_BAR,
+ SingleForeignEnum = ForeignEnum.ForeignBar,
SingleForeignMessage = new ForeignMessage { C = 10 },
- SingleImportEnum = ImportEnum.IMPORT_BAZ,
+ SingleImportEnum = ImportEnum.ImportBaz,
SingleImportMessage = new ImportMessage { D = 20 },
SingleInt32 = 100,
SingleInt64 = 3210987654321,
- SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO,
+ SingleNestedEnum = TestAllTypes.Types.NestedEnum.Foo,
SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 },
SinglePublicImportMessage = new PublicImportMessage { E = 54 },
SingleSfixed32 = -123,
@@ -179,13 +179,13 @@ namespace Google.Protobuf RepeatedFixed32 = { uint.MaxValue, 23 },
RepeatedFixed64 = { ulong.MaxValue, 1234567890123 },
RepeatedFloat = { 100f, 12.25f },
- RepeatedForeignEnum = { ForeignEnum.FOREIGN_FOO, ForeignEnum.FOREIGN_BAR },
+ RepeatedForeignEnum = { ForeignEnum.ForeignFoo, ForeignEnum.ForeignBar },
RepeatedForeignMessage = { new ForeignMessage(), new ForeignMessage { C = 10 } },
- RepeatedImportEnum = { ImportEnum.IMPORT_BAZ, ImportEnum.IMPORT_ENUM_UNSPECIFIED },
+ RepeatedImportEnum = { ImportEnum.ImportBaz, ImportEnum.Unspecified },
RepeatedImportMessage = { new ImportMessage { D = 20 }, new ImportMessage { D = 25 } },
RepeatedInt32 = { 100, 200 },
RepeatedInt64 = { 3210987654321, long.MaxValue },
- RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.NEG },
+ RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.Foo, 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 },
@@ -224,8 +224,8 @@ namespace Google.Protobuf { 5, new ForeignMessage() },
},
MapInt32Enum = {
- { 1, MapEnum.MAP_ENUM_BAR },
- { 2000, MapEnum.MAP_ENUM_FOO }
+ { 1, MapEnum.Bar },
+ { 2000, MapEnum.Foo }
}
};
@@ -249,7 +249,7 @@ namespace Google.Protobuf Assert.AreEqual(1, parsed.MapInt32Bytes.Count);
Assert.AreEqual(ByteString.Empty, parsed.MapInt32Bytes[0]);
}
-
+
[Test]
public void MapWithOnlyValue()
{
@@ -449,7 +449,7 @@ namespace Google.Protobuf SingleFloat = 12.25f,
SingleInt32 = 100,
SingleInt64 = 3210987654321,
- SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO,
+ SingleNestedEnum = TestAllTypes.Types.NestedEnum.Foo,
SingleSfixed32 = -123,
SingleSfixed64 = -12345678901234,
SingleSint32 = -456,
@@ -479,7 +479,7 @@ namespace Google.Protobuf RepeatedFloat = { 100f, 12.25f },
RepeatedInt32 = { 100, 200 },
RepeatedInt64 = { 3210987654321, long.MaxValue },
- RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.NEG },
+ RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.Foo, TestAllTypes.Types.NestedEnum.Neg },
RepeatedSfixed32 = { -123, 123 },
RepeatedSfixed64 = { -12345678901234, 12345678901234 },
RepeatedSint32 = { -456, 100 },
@@ -670,7 +670,7 @@ namespace Google.Protobuf {
// 130, 3 is the message tag
// 1 is the data length - but there's no data.
- var data = new byte[] { 130, 3, 1 };
+ var data = new byte[] { 130, 3, 1 };
Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(data));
}
@@ -720,4 +720,4 @@ namespace Google.Protobuf Assert.AreEqual("{ \"c\": 31 }", writer.ToString());
}
}
-}
+}
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs index 344d727b..0b6cd7e6 100644 --- a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs @@ -75,13 +75,13 @@ namespace Google.Protobuf SingleFixed32 = 23, SingleFixed64 = 1234567890123, SingleFloat = 12.25f, - SingleForeignEnum = ForeignEnum.FOREIGN_BAR, + SingleForeignEnum = ForeignEnum.ForeignBar, SingleForeignMessage = new ForeignMessage { C = 10 }, - SingleImportEnum = ImportEnum.IMPORT_BAZ, + SingleImportEnum = ImportEnum.ImportBaz, SingleImportMessage = new ImportMessage { D = 20 }, SingleInt32 = 100, SingleInt64 = 3210987654321, - SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO, + SingleNestedEnum = TestAllTypes.Types.NestedEnum.Foo, SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 }, SinglePublicImportMessage = new PublicImportMessage { E = 54 }, SingleSfixed32 = -123, @@ -174,14 +174,14 @@ namespace Google.Protobuf [Test] public void UnknownEnumValueNumeric_RepeatedField() { - var message = new TestAllTypes { RepeatedForeignEnum = { ForeignEnum.FOREIGN_BAZ, (ForeignEnum) 100, ForeignEnum.FOREIGN_FOO } }; + var message = new TestAllTypes { RepeatedForeignEnum = { ForeignEnum.ForeignBaz, (ForeignEnum) 100, ForeignEnum.ForeignFoo } }; AssertJson("{ 'repeatedForeignEnum': [ 'FOREIGN_BAZ', 100, 'FOREIGN_FOO' ] }", JsonFormatter.Default.Format(message)); } [Test] public void UnknownEnumValueNumeric_MapField() { - var message = new TestMap { MapInt32Enum = { { 1, MapEnum.MAP_ENUM_FOO }, { 2, (MapEnum) 100 }, { 3, MapEnum.MAP_ENUM_BAR } } }; + var message = new TestMap { MapInt32Enum = { { 1, MapEnum.Foo }, { 2, (MapEnum) 100 }, { 3, MapEnum.Bar } } }; AssertJson("{ 'mapInt32Enum': { '1': 'MAP_ENUM_FOO', '2': 100, '3': 'MAP_ENUM_BAR' } }", JsonFormatter.Default.Format(message)); } diff --git a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs index d21da58a..684f52b4 100644 --- a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs @@ -142,8 +142,8 @@ namespace Google.Protobuf [TestCase(typeof(DoubleValue), "1.5", 1.5d)] public void Wrappers_Standalone(System.Type wrapperType, string json, object expectedValue) { - IMessage parsed = (IMessage) Activator.CreateInstance(wrapperType); - IMessage expected = (IMessage) Activator.CreateInstance(wrapperType); + IMessage parsed = (IMessage)Activator.CreateInstance(wrapperType); + IMessage expected = (IMessage)Activator.CreateInstance(wrapperType); JsonParser.Default.Merge(parsed, "null"); Assert.AreEqual(expected, parsed); @@ -640,7 +640,7 @@ namespace Google.Protobuf var parsed = Timestamp.Parser.ParseJson(json); Assert.AreEqual(WrapInQuotes(expectedFormatted), parsed.ToString()); } - + [Test] [TestCase("2015-10-09 14:46:23.123456789Z", Description = "No T between date and time")] [TestCase("2015/10/09T14:46:23.123456789Z", Description = "Wrong date separators")] @@ -886,9 +886,9 @@ namespace Google.Protobuf } [Test] - [TestCase("\"FOREIGN_BAR\"", ForeignEnum.FOREIGN_BAR)] - [TestCase("5", ForeignEnum.FOREIGN_BAR)] - [TestCase("100", (ForeignEnum) 100)] + [TestCase("\"FOREIGN_BAR\"", ForeignEnum.ForeignBar)] + [TestCase("5", ForeignEnum.ForeignBar)] + [TestCase("100", (ForeignEnum)100)] public void EnumValid(string value, ForeignEnum expectedValue) { string json = "{ \"singleForeignEnum\": " + value + " }"; @@ -922,4 +922,4 @@ namespace Google.Protobuf return '"' + text + '"'; } } -} +}
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs index 086a4e98..52d5a676 100644 --- a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs +++ b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs @@ -195,7 +195,7 @@ namespace Google.Protobuf.Reflection Assert.AreEqual(value, enumType.Values[1]); Assert.AreEqual("FOREIGN_FOO", value.Name); Assert.AreEqual(4, value.Number); - Assert.AreEqual((int) ForeignEnum.FOREIGN_FOO, value.Number); + Assert.AreEqual((int) ForeignEnum.ForeignFoo, value.Number); Assert.AreEqual(value, enumType.FindValueByNumber(4)); Assert.Null(enumType.FindValueByName("NO_SUCH_VALUE")); for (int i = 0; i < enumType.Values.Count; i++) diff --git a/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs index 936e41c6..a488af30 100644 --- a/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs +++ b/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs @@ -128,7 +128,7 @@ namespace Google.Protobuf.Reflection 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.FOREIGN_FOO); + 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); @@ -138,7 +138,7 @@ namespace Google.Protobuf.Reflection SingleInt32 = 500, SingleString = "It's a string", SingleBytes = ByteString.CopyFrom(99, 98, 97), - SingleForeignEnum = ForeignEnum.FOREIGN_FOO, + SingleForeignEnum = ForeignEnum.ForeignFoo, SingleForeignMessage = new ForeignMessage { C = 12345 }, SingleDouble = 20150701.5 }; diff --git a/csharp/src/Google.Protobuf.Test/SampleMessages.cs b/csharp/src/Google.Protobuf.Test/SampleMessages.cs index 8a9c7f86..ffa4e2a7 100644 --- a/csharp/src/Google.Protobuf.Test/SampleMessages.cs +++ b/csharp/src/Google.Protobuf.Test/SampleMessages.cs @@ -54,13 +54,13 @@ namespace Google.Protobuf SingleFixed32 = 23, SingleFixed64 = 1234567890123, SingleFloat = 12.25f, - SingleForeignEnum = ForeignEnum.FOREIGN_BAR, + SingleForeignEnum = ForeignEnum.ForeignBar, SingleForeignMessage = new ForeignMessage { C = 10 }, - SingleImportEnum = ImportEnum.IMPORT_BAZ, + SingleImportEnum = ImportEnum.ImportBaz, SingleImportMessage = new ImportMessage { D = 20 }, SingleInt32 = 100, SingleInt64 = 3210987654321, - SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO, + SingleNestedEnum = TestAllTypes.Types.NestedEnum.Foo, SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 }, SinglePublicImportMessage = new PublicImportMessage { E = 54 }, SingleSfixed32 = -123, @@ -76,13 +76,13 @@ namespace Google.Protobuf RepeatedFixed32 = { UInt32.MaxValue, 23 }, RepeatedFixed64 = { UInt64.MaxValue, 1234567890123 }, RepeatedFloat = { 100f, 12.25f }, - RepeatedForeignEnum = { ForeignEnum.FOREIGN_FOO, ForeignEnum.FOREIGN_BAR }, + RepeatedForeignEnum = { ForeignEnum.ForeignFoo, ForeignEnum.ForeignBar }, RepeatedForeignMessage = { new ForeignMessage(), new ForeignMessage { C = 10 } }, - RepeatedImportEnum = { ImportEnum.IMPORT_BAZ, ImportEnum.IMPORT_ENUM_UNSPECIFIED }, + RepeatedImportEnum = { ImportEnum.ImportBaz, ImportEnum.Unspecified }, 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 = { TestAllTypes.Types.NestedEnum.Foo, 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 }, @@ -92,8 +92,8 @@ namespace Google.Protobuf RepeatedString = { "foo", "bar" }, RepeatedUint32 = { UInt32.MaxValue, UInt32.MinValue }, RepeatedUint64 = { UInt64.MaxValue, UInt32.MinValue }, - OneofString = "Oneof string" + OneofString = "Oneof string" }; } } -} +}
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/TestCornerCases.cs b/csharp/src/Google.Protobuf.Test/TestCornerCases.cs index 03fa1855..248f5fa9 100644 --- a/csharp/src/Google.Protobuf.Test/TestCornerCases.cs +++ b/csharp/src/Google.Protobuf.Test/TestCornerCases.cs @@ -43,8 +43,8 @@ namespace Google.Protobuf NegativeEnumMessage msg = new NegativeEnumMessage
{
Value = NegativeEnum.MinusOne,
- Values = { NegativeEnum.NEGATIVE_ENUM_ZERO, NegativeEnum.MinusOne, NegativeEnum.FiveBelow },
- PackedValues = { NegativeEnum.NEGATIVE_ENUM_ZERO, NegativeEnum.MinusOne, NegativeEnum.FiveBelow }
+ Values = { NegativeEnum.Zero, NegativeEnum.MinusOne, NegativeEnum.FiveBelow },
+ PackedValues = { NegativeEnum.Zero, NegativeEnum.MinusOne, NegativeEnum.FiveBelow }
};
Assert.AreEqual(58, msg.CalculateSize());
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs index 27c04787..3ba4a2b6 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs @@ -164,9 +164,9 @@ namespace Google.Protobuf.TestProtos { } #region Enums public enum MapEnum { - MAP_ENUM_FOO = 0, - MAP_ENUM_BAR = 1, - MAP_ENUM_BAZ = 2, + [pbr::OriginalName("MAP_ENUM_FOO")] Foo = 0, + [pbr::OriginalName("MAP_ENUM_BAR")] Bar = 1, + [pbr::OriginalName("MAP_ENUM_BAZ")] Baz = 2, } #endregion @@ -1358,7 +1358,7 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Types { public enum Type { - TYPE_FOO = 0, + [pbr::OriginalName("TYPE_FOO")] Foo = 0, } } diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs index 7b824dc7..263e17c0 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs @@ -42,10 +42,10 @@ namespace Google.Protobuf.TestProtos { } #region Enums public enum ImportEnum { - IMPORT_ENUM_UNSPECIFIED = 0, - IMPORT_FOO = 7, - IMPORT_BAR = 8, - IMPORT_BAZ = 9, + [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 diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs index 586f01c8..7d4451b0 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs @@ -66,14 +66,14 @@ namespace UnitTest.Issues.TestProtos { } #region Enums public enum NegativeEnum { - NEGATIVE_ENUM_ZERO = 0, - FiveBelow = -5, - MinusOne = -1, + [pbr::OriginalName("NEGATIVE_ENUM_ZERO")] Zero = 0, + [pbr::OriginalName("FiveBelow")] FiveBelow = -5, + [pbr::OriginalName("MinusOne")] MinusOne = -1, } public enum DeprecatedEnum { - DEPRECATED_ZERO = 0, - one = 1, + [pbr::OriginalName("DEPRECATED_ZERO")] DeprecatedZero = 0, + [pbr::OriginalName("one")] One = 1, } #endregion @@ -356,7 +356,7 @@ namespace UnitTest.Issues.TestProtos { /// <summary>Field number for the "value" field.</summary> public const int ValueFieldNumber = 1; - private global::UnitTest.Issues.TestProtos.NegativeEnum value_ = global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO; + private global::UnitTest.Issues.TestProtos.NegativeEnum value_ = 0; public global::UnitTest.Issues.TestProtos.NegativeEnum Value { get { return value_; } set { @@ -401,7 +401,7 @@ namespace UnitTest.Issues.TestProtos { public override int GetHashCode() { int hash = 1; - if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) hash ^= Value.GetHashCode(); + if (Value != 0) hash ^= Value.GetHashCode(); hash ^= values_.GetHashCode(); hash ^= packedValues_.GetHashCode(); return hash; @@ -412,7 +412,7 @@ namespace UnitTest.Issues.TestProtos { } public void WriteTo(pb::CodedOutputStream output) { - if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) { + if (Value != 0) { output.WriteRawTag(8); output.WriteEnum((int) Value); } @@ -422,7 +422,7 @@ namespace UnitTest.Issues.TestProtos { public int CalculateSize() { int size = 0; - if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) { + if (Value != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Value); } size += values_.CalculateSize(_repeated_values_codec); @@ -434,7 +434,7 @@ namespace UnitTest.Issues.TestProtos { if (other == null) { return; } - if (other.Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) { + if (other.Value != 0) { Value = other.Value; } values_.Add(other.values_); @@ -620,7 +620,7 @@ namespace UnitTest.Issues.TestProtos { /// <summary>Field number for the "EnumValue" field.</summary> public const int EnumValueFieldNumber = 5; - private global::UnitTest.Issues.TestProtos.DeprecatedEnum enumValue_ = global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO; + private global::UnitTest.Issues.TestProtos.DeprecatedEnum enumValue_ = 0; [global::System.ObsoleteAttribute()] public global::UnitTest.Issues.TestProtos.DeprecatedEnum EnumValue { get { return enumValue_; } @@ -665,7 +665,7 @@ namespace UnitTest.Issues.TestProtos { hash ^= primitiveArray_.GetHashCode(); if (messageValue_ != null) hash ^= MessageValue.GetHashCode(); hash ^= messageArray_.GetHashCode(); - if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) hash ^= EnumValue.GetHashCode(); + if (EnumValue != 0) hash ^= EnumValue.GetHashCode(); hash ^= enumArray_.GetHashCode(); return hash; } @@ -685,7 +685,7 @@ namespace UnitTest.Issues.TestProtos { output.WriteMessage(MessageValue); } messageArray_.WriteTo(output, _repeated_messageArray_codec); - if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) { + if (EnumValue != 0) { output.WriteRawTag(40); output.WriteEnum((int) EnumValue); } @@ -702,7 +702,7 @@ namespace UnitTest.Issues.TestProtos { size += 1 + pb::CodedOutputStream.ComputeMessageSize(MessageValue); } size += messageArray_.CalculateSize(_repeated_messageArray_codec); - if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) { + if (EnumValue != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumValue); } size += enumArray_.CalculateSize(_repeated_enumArray_codec); @@ -724,7 +724,7 @@ namespace UnitTest.Issues.TestProtos { MessageValue.MergeFrom(other.MessageValue); } messageArray_.Add(other.messageArray_); - if (other.EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) { + if (other.EnumValue != 0) { EnumValue = other.EnumValue; } enumArray_.Add(other.enumArray_); @@ -1435,7 +1435,7 @@ namespace UnitTest.Issues.TestProtos { public const int NameFieldNumber = 1; private string name_ = ""; /// <summary> - /// json_name field options are not properly handled during deserialization + /// Message for testing the effects for of the json_name option /// </summary> public string Name { get { return name_; } diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs index d8465448..b8d159bb 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs @@ -193,39 +193,39 @@ namespace Google.Protobuf.TestProtos { } #region Enums public enum ForeignEnum { - FOREIGN_UNSPECIFIED = 0, - FOREIGN_FOO = 4, - FOREIGN_BAR = 5, - FOREIGN_BAZ = 6, + [pbr::OriginalName("FOREIGN_UNSPECIFIED")] ForeignUnspecified = 0, + [pbr::OriginalName("FOREIGN_FOO")] ForeignFoo = 4, + [pbr::OriginalName("FOREIGN_BAR")] ForeignBar = 5, + [pbr::OriginalName("FOREIGN_BAZ")] ForeignBaz = 6, } /// <summary> /// Test an enum that has multiple values with the same number. /// </summary> public enum TestEnumWithDupValue { - TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED = 0, - FOO1 = 1, - BAR1 = 2, - BAZ = 3, - FOO2 = 1, - BAR2 = 2, + [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")] Foo2 = 1, + [pbr::OriginalName("BAR2")] Bar2 = 2, } /// <summary> /// Test an enum with large, unordered values. /// </summary> public enum TestSparseEnum { - TEST_SPARSE_ENUM_UNSPECIFIED = 0, - SPARSE_A = 123, - SPARSE_B = 62374, - SPARSE_C = 12589234, - SPARSE_D = -15, - SPARSE_E = -53452, + [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, /// <summary> /// In proto3, value 0 must be the first one specified /// SPARSE_F = 0; /// </summary> - SPARSE_G = 2, + [pbr::OriginalName("SPARSE_G")] SparseG = 2, } #endregion @@ -505,7 +505,7 @@ namespace Google.Protobuf.TestProtos { /// <summary>Field number for the "single_nested_enum" field.</summary> public const int SingleNestedEnumFieldNumber = 21; - private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum singleNestedEnum_ = global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED; + private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum singleNestedEnum_ = 0; public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum SingleNestedEnum { get { return singleNestedEnum_; } set { @@ -515,7 +515,7 @@ namespace Google.Protobuf.TestProtos { /// <summary>Field number for the "single_foreign_enum" field.</summary> public const int SingleForeignEnumFieldNumber = 22; - private global::Google.Protobuf.TestProtos.ForeignEnum singleForeignEnum_ = global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED; + private global::Google.Protobuf.TestProtos.ForeignEnum singleForeignEnum_ = 0; public global::Google.Protobuf.TestProtos.ForeignEnum SingleForeignEnum { get { return singleForeignEnum_; } set { @@ -525,7 +525,7 @@ namespace Google.Protobuf.TestProtos { /// <summary>Field number for the "single_import_enum" field.</summary> public const int SingleImportEnumFieldNumber = 23; - private global::Google.Protobuf.TestProtos.ImportEnum singleImportEnum_ = global::Google.Protobuf.TestProtos.ImportEnum.IMPORT_ENUM_UNSPECIFIED; + private global::Google.Protobuf.TestProtos.ImportEnum singleImportEnum_ = 0; public global::Google.Protobuf.TestProtos.ImportEnum SingleImportEnum { get { return singleImportEnum_; } set { @@ -892,9 +892,9 @@ namespace Google.Protobuf.TestProtos { 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.NESTED_ENUM_UNSPECIFIED) hash ^= SingleNestedEnum.GetHashCode(); - if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) hash ^= SingleForeignEnum.GetHashCode(); - if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.IMPORT_ENUM_UNSPECIFIED) hash ^= SingleImportEnum.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(); @@ -1003,15 +1003,15 @@ namespace Google.Protobuf.TestProtos { output.WriteRawTag(162, 1); output.WriteMessage(SingleImportMessage); } - if (SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED) { + if (SingleNestedEnum != 0) { output.WriteRawTag(168, 1); output.WriteEnum((int) SingleNestedEnum); } - if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) { + if (SingleForeignEnum != 0) { output.WriteRawTag(176, 1); output.WriteEnum((int) SingleForeignEnum); } - if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.IMPORT_ENUM_UNSPECIFIED) { + if (SingleImportEnum != 0) { output.WriteRawTag(184, 1); output.WriteEnum((int) SingleImportEnum); } @@ -1115,13 +1115,13 @@ namespace Google.Protobuf.TestProtos { if (singleImportMessage_ != null) { size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleImportMessage); } - if (SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED) { + if (SingleNestedEnum != 0) { size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) SingleNestedEnum); } - if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) { + if (SingleForeignEnum != 0) { size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) SingleForeignEnum); } - if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.IMPORT_ENUM_UNSPECIFIED) { + if (SingleImportEnum != 0) { size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) SingleImportEnum); } if (singlePublicImportMessage_ != null) { @@ -1231,13 +1231,13 @@ namespace Google.Protobuf.TestProtos { } SingleImportMessage.MergeFrom(other.SingleImportMessage); } - if (other.SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED) { + if (other.SingleNestedEnum != 0) { SingleNestedEnum = other.SingleNestedEnum; } - if (other.SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) { + if (other.SingleForeignEnum != 0) { SingleForeignEnum = other.SingleForeignEnum; } - if (other.SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.IMPORT_ENUM_UNSPECIFIED) { + if (other.SingleImportEnum != 0) { SingleImportEnum = other.SingleImportEnum; } if (other.singlePublicImportMessage_ != null) { @@ -1526,14 +1526,14 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Types { public enum NestedEnum { - NESTED_ENUM_UNSPECIFIED = 0, - FOO = 1, - BAR = 2, - BAZ = 3, + [pbr::OriginalName("NESTED_ENUM_UNSPECIFIED")] Unspecified = 0, + [pbr::OriginalName("FOO")] Foo = 1, + [pbr::OriginalName("BAR")] Bar = 2, + [pbr::OriginalName("BAZ")] Baz = 3, /// <summary> /// Intentionally negative. /// </summary> - NEG = -1, + [pbr::OriginalName("NEG")] Neg = -1, } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] @@ -2793,7 +2793,7 @@ namespace Google.Protobuf.TestProtos { /// <summary>Field number for the "EnumField" field.</summary> public const int EnumFieldFieldNumber = 3; - private global::Google.Protobuf.TestProtos.ForeignEnum enumField_ = global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED; + private global::Google.Protobuf.TestProtos.ForeignEnum enumField_ = 0; public global::Google.Protobuf.TestProtos.ForeignEnum EnumField { get { return enumField_; } set { @@ -2873,7 +2873,7 @@ namespace Google.Protobuf.TestProtos { int hash = 1; if (PrimitiveField != 0) hash ^= PrimitiveField.GetHashCode(); if (StringField.Length != 0) hash ^= StringField.GetHashCode(); - if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) hash ^= EnumField.GetHashCode(); + if (EnumField != 0) hash ^= EnumField.GetHashCode(); if (messageField_ != null) hash ^= MessageField.GetHashCode(); hash ^= repeatedPrimitiveField_.GetHashCode(); hash ^= repeatedStringField_.GetHashCode(); @@ -2895,7 +2895,7 @@ namespace Google.Protobuf.TestProtos { output.WriteRawTag(18); output.WriteString(StringField); } - if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) { + if (EnumField != 0) { output.WriteRawTag(24); output.WriteEnum((int) EnumField); } @@ -2917,7 +2917,7 @@ namespace Google.Protobuf.TestProtos { if (StringField.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(StringField); } - if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) { + if (EnumField != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumField); } if (messageField_ != null) { @@ -2940,7 +2940,7 @@ namespace Google.Protobuf.TestProtos { if (other.StringField.Length != 0) { StringField = other.StringField; } - if (other.EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) { + if (other.EnumField != 0) { EnumField = other.EnumField; } if (other.messageField_ != null) { @@ -3370,7 +3370,7 @@ namespace Google.Protobuf.TestProtos { /// <summary>Field number for the "sparse_enum" field.</summary> public const int SparseEnumFieldNumber = 1; - private global::Google.Protobuf.TestProtos.TestSparseEnum sparseEnum_ = global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED; + private global::Google.Protobuf.TestProtos.TestSparseEnum sparseEnum_ = 0; public global::Google.Protobuf.TestProtos.TestSparseEnum SparseEnum { get { return sparseEnum_; } set { @@ -3395,7 +3395,7 @@ namespace Google.Protobuf.TestProtos { public override int GetHashCode() { int hash = 1; - if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED) hash ^= SparseEnum.GetHashCode(); + if (SparseEnum != 0) hash ^= SparseEnum.GetHashCode(); return hash; } @@ -3404,7 +3404,7 @@ namespace Google.Protobuf.TestProtos { } public void WriteTo(pb::CodedOutputStream output) { - if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED) { + if (SparseEnum != 0) { output.WriteRawTag(8); output.WriteEnum((int) SparseEnum); } @@ -3412,7 +3412,7 @@ namespace Google.Protobuf.TestProtos { public int CalculateSize() { int size = 0; - if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED) { + if (SparseEnum != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) SparseEnum); } return size; @@ -3422,7 +3422,7 @@ namespace Google.Protobuf.TestProtos { if (other == null) { return; } - if (other.SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED) { + if (other.SparseEnum != 0) { SparseEnum = other.SparseEnum; } } diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj index ef524baf..5557612a 100644 --- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj +++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj @@ -117,6 +117,7 @@ <Compile Include="Reflection\MethodDescriptor.cs" />
<Compile Include="Reflection\OneofAccessor.cs" />
<Compile Include="Reflection\OneofDescriptor.cs" />
+ <Compile Include="Reflection\OriginalNameAttribute.cs" />
<Compile Include="Reflection\PackageDescriptor.cs" />
<Compile Include="Reflection\PartialClasses.cs" />
<Compile Include="Reflection\ReflectionUtil.cs" />
diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.nuspec b/csharp/src/Google.Protobuf/Google.Protobuf.nuspec index f51bc89a..2892b8bf 100644 --- a/csharp/src/Google.Protobuf/Google.Protobuf.nuspec +++ b/csharp/src/Google.Protobuf/Google.Protobuf.nuspec @@ -33,10 +33,12 @@ <dependency id="System.Linq.Expressions" version="4.0.0" /> <dependency id="System.ObjectModel" version="4.0.0" /> <dependency id="System.Reflection" version="4.0.0" /> + <dependency id="System.Reflection.Extensions" version="4.0.0" /> <dependency id="System.Runtime" version="4.0.0" /> <dependency id="System.Runtime.Extensions" version="4.0.0" /> <dependency id="System.Text.Encoding" version="4.0.0" /> <dependency id="System.Text.RegularExpressions" version="4.0.0" /> + <dependency id="System.Threading" version="4.0.0" /> </group> </dependencies> </metadata> diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs index cbd9366c..73a4f64b 100644 --- a/csharp/src/Google.Protobuf/JsonFormatter.cs +++ b/csharp/src/Google.Protobuf/JsonFormatter.cs @@ -39,6 +39,7 @@ using Google.Protobuf.WellKnownTypes; using System.IO; using System.Linq; using System.Collections.Generic; +using System.Reflection; namespace Google.Protobuf { @@ -420,9 +421,10 @@ namespace Google.Protobuf } else if (value is System.Enum) { - if (System.Enum.IsDefined(value.GetType(), value)) + string name = OriginalEnumValueHelper.GetOriginalName(value); + if (name != null) { - WriteString(writer, value.ToString()); + WriteString(writer, name); } else { @@ -877,5 +879,44 @@ namespace Google.Protobuf TypeRegistry = ProtoPreconditions.CheckNotNull(typeRegistry, nameof(typeRegistry)); } } + + // Effectively a cache of mapping from enum values to the original name as specified in the proto file, + // fetched by reflection. + // The need for this is unfortunate, as is its unbounded size, but realistically it shouldn't cause issues. + private static class OriginalEnumValueHelper + { + // TODO: In the future we might want to use ConcurrentDictionary, at the point where all + // the platforms we target have it. + private static readonly Dictionary<System.Type, Dictionary<object, string>> dictionaries + = new Dictionary<System.Type, Dictionary<object, string>>(); + + internal static string GetOriginalName(object value) + { + var enumType = value.GetType(); + Dictionary<object, string> nameMapping; + lock (dictionaries) + { + if (!dictionaries.TryGetValue(enumType, out nameMapping)) + { + nameMapping = GetNameMapping(enumType); + dictionaries[enumType] = nameMapping; + } + } + + string originalName; + // If this returns false, originalName will be null, which is what we want. + nameMapping.TryGetValue(value, out originalName); + return originalName; + } + + private static Dictionary<object, string> GetNameMapping(System.Type enumType) => + enumType.GetTypeInfo().DeclaredFields + .Where(f => f.IsStatic) + .ToDictionary(f => f.GetValue(null), + f => f.GetCustomAttributes<OriginalNameAttribute>() + .FirstOrDefault() + // If the attribute hasn't been applied, fall back to the name of the field. + ?.Name ?? f.Name); + } } } diff --git a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs index 7de7b5fc..fa138dfe 100644 --- a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs @@ -80,7 +80,7 @@ namespace Google.Protobuf.Reflection { "EhMKC291dHB1dF90eXBlGAMgASgJEi8KB29wdGlvbnMYBCABKAsyHi5nb29n", "bGUucHJvdG9idWYuTWV0aG9kT3B0aW9ucxIfChBjbGllbnRfc3RyZWFtaW5n", "GAUgASgIOgVmYWxzZRIfChBzZXJ2ZXJfc3RyZWFtaW5nGAYgASgIOgVmYWxz", - "ZSKuBQoLRmlsZU9wdGlvbnMSFAoMamF2YV9wYWNrYWdlGAEgASgJEhwKFGph", + "ZSKHBQoLRmlsZU9wdGlvbnMSFAoMamF2YV9wYWNrYWdlGAEgASgJEhwKFGph", "dmFfb3V0ZXJfY2xhc3NuYW1lGAggASgJEiIKE2phdmFfbXVsdGlwbGVfZmls", "ZXMYCiABKAg6BWZhbHNlEiwKHWphdmFfZ2VuZXJhdGVfZXF1YWxzX2FuZF9o", "YXNoGBQgASgIOgVmYWxzZRIlChZqYXZhX3N0cmluZ19jaGVja191dGY4GBsg", @@ -91,54 +91,53 @@ namespace Google.Protobuf.Reflection { "cHlfZ2VuZXJpY19zZXJ2aWNlcxgSIAEoCDoFZmFsc2USGQoKZGVwcmVjYXRl", "ZBgXIAEoCDoFZmFsc2USHwoQY2NfZW5hYmxlX2FyZW5hcxgfIAEoCDoFZmFs", "c2USGQoRb2JqY19jbGFzc19wcmVmaXgYJCABKAkSGAoQY3NoYXJwX25hbWVz", - "cGFjZRglIAEoCRIrCh9qYXZhbmFub191c2VfZGVwcmVjYXRlZF9wYWNrYWdl", - "GCYgASgIQgIYARJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5n", + "cGFjZRglIAEoCRJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5n", "b29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbiI6CgxPcHRpbWl6", "ZU1vZGUSCQoFU1BFRUQQARINCglDT0RFX1NJWkUQAhIQCgxMSVRFX1JVTlRJ", - "TUUQAyoJCOgHEICAgIACIuYBCg5NZXNzYWdlT3B0aW9ucxImChdtZXNzYWdl", - "X3NldF93aXJlX2Zvcm1hdBgBIAEoCDoFZmFsc2USLgofbm9fc3RhbmRhcmRf", - "ZGVzY3JpcHRvcl9hY2Nlc3NvchgCIAEoCDoFZmFsc2USGQoKZGVwcmVjYXRl", - "ZBgDIAEoCDoFZmFsc2USEQoJbWFwX2VudHJ5GAcgASgIEkMKFHVuaW50ZXJw", - "cmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVy", - "cHJldGVkT3B0aW9uKgkI6AcQgICAgAIimAMKDEZpZWxkT3B0aW9ucxI6CgVj", - "dHlwZRgBIAEoDjIjLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlvbnMuQ1R5", - "cGU6BlNUUklORxIOCgZwYWNrZWQYAiABKAgSPwoGanN0eXBlGAYgASgOMiQu", - "Z29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5KU1R5cGU6CUpTX05PUk1B", - "TBITCgRsYXp5GAUgASgIOgVmYWxzZRIZCgpkZXByZWNhdGVkGAMgASgIOgVm", - "YWxzZRITCgR3ZWFrGAogASgIOgVmYWxzZRJDChR1bmludGVycHJldGVkX29w", + "TUUQAyoJCOgHEICAgIACSgQIJhAnIuYBCg5NZXNzYWdlT3B0aW9ucxImChdt", + "ZXNzYWdlX3NldF93aXJlX2Zvcm1hdBgBIAEoCDoFZmFsc2USLgofbm9fc3Rh", + "bmRhcmRfZGVzY3JpcHRvcl9hY2Nlc3NvchgCIAEoCDoFZmFsc2USGQoKZGVw", + "cmVjYXRlZBgDIAEoCDoFZmFsc2USEQoJbWFwX2VudHJ5GAcgASgIEkMKFHVu", + "aW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5V", + "bmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIimAMKDEZpZWxkT3B0aW9u", + "cxI6CgVjdHlwZRgBIAEoDjIjLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlv", + "bnMuQ1R5cGU6BlNUUklORxIOCgZwYWNrZWQYAiABKAgSPwoGanN0eXBlGAYg", + "ASgOMiQuZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5KU1R5cGU6CUpT", + "X05PUk1BTBITCgRsYXp5GAUgASgIOgVmYWxzZRIZCgpkZXByZWNhdGVkGAMg", + "ASgIOgVmYWxzZRITCgR3ZWFrGAogASgIOgVmYWxzZRJDChR1bmludGVycHJl", + "dGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnBy", + "ZXRlZE9wdGlvbiIvCgVDVHlwZRIKCgZTVFJJTkcQABIICgRDT1JEEAESEAoM", + "U1RSSU5HX1BJRUNFEAIiNQoGSlNUeXBlEg0KCUpTX05PUk1BTBAAEg0KCUpT", + "X1NUUklORxABEg0KCUpTX05VTUJFUhACKgkI6AcQgICAgAIijQEKC0VudW1P", + "cHRpb25zEhMKC2FsbG93X2FsaWFzGAIgASgIEhkKCmRlcHJlY2F0ZWQYAyAB", + "KAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdv", + "b2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIi", + "fQoQRW51bVZhbHVlT3B0aW9ucxIZCgpkZXByZWNhdGVkGAEgASgIOgVmYWxz", + "ZRJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJv", + "dG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbioJCOgHEICAgIACInsKDlNlcnZp", + "Y2VPcHRpb25zEhkKCmRlcHJlY2F0ZWQYISABKAg6BWZhbHNlEkMKFHVuaW50", + "ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5Vbmlu", + "dGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIiegoNTWV0aG9kT3B0aW9ucxIZ", + "CgpkZXByZWNhdGVkGCEgASgIOgVmYWxzZRJDChR1bmludGVycHJldGVkX29w", "dGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9w", - "dGlvbiIvCgVDVHlwZRIKCgZTVFJJTkcQABIICgRDT1JEEAESEAoMU1RSSU5H", - "X1BJRUNFEAIiNQoGSlNUeXBlEg0KCUpTX05PUk1BTBAAEg0KCUpTX1NUUklO", - "RxABEg0KCUpTX05VTUJFUhACKgkI6AcQgICAgAIijQEKC0VudW1PcHRpb25z", - "EhMKC2FsbG93X2FsaWFzGAIgASgIEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZh", - "bHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5w", - "cm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIifQoQRW51", - "bVZhbHVlT3B0aW9ucxIZCgpkZXByZWNhdGVkGAEgASgIOgVmYWxzZRJDChR1", - "bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYu", - "VW5pbnRlcnByZXRlZE9wdGlvbioJCOgHEICAgIACInsKDlNlcnZpY2VPcHRp", - "b25zEhkKCmRlcHJlY2F0ZWQYISABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0", - "ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJl", - "dGVkT3B0aW9uKgkI6AcQgICAgAIiegoNTWV0aG9kT3B0aW9ucxIZCgpkZXBy", - "ZWNhdGVkGCEgASgIOgVmYWxzZRJDChR1bmludGVycHJldGVkX29wdGlvbhjn", - "ByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbioJ", - "COgHEICAgIACIp4CChNVbmludGVycHJldGVkT3B0aW9uEjsKBG5hbWUYAiAD", - "KAsyLS5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbi5OYW1l", - "UGFydBIYChBpZGVudGlmaWVyX3ZhbHVlGAMgASgJEhoKEnBvc2l0aXZlX2lu", - "dF92YWx1ZRgEIAEoBBIaChJuZWdhdGl2ZV9pbnRfdmFsdWUYBSABKAMSFAoM", - "ZG91YmxlX3ZhbHVlGAYgASgBEhQKDHN0cmluZ192YWx1ZRgHIAEoDBIXCg9h", - "Z2dyZWdhdGVfdmFsdWUYCCABKAkaMwoITmFtZVBhcnQSEQoJbmFtZV9wYXJ0", - "GAEgAigJEhQKDGlzX2V4dGVuc2lvbhgCIAIoCCLVAQoOU291cmNlQ29kZUlu", - "Zm8SOgoIbG9jYXRpb24YASADKAsyKC5nb29nbGUucHJvdG9idWYuU291cmNl", - "Q29kZUluZm8uTG9jYXRpb24ahgEKCExvY2F0aW9uEhAKBHBhdGgYASADKAVC", - "AhABEhAKBHNwYW4YAiADKAVCAhABEhgKEGxlYWRpbmdfY29tbWVudHMYAyAB", - "KAkSGQoRdHJhaWxpbmdfY29tbWVudHMYBCABKAkSIQoZbGVhZGluZ19kZXRh", - "Y2hlZF9jb21tZW50cxgGIAMoCSKnAQoRR2VuZXJhdGVkQ29kZUluZm8SQQoK", - "YW5ub3RhdGlvbhgBIAMoCzItLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRD", - "b2RlSW5mby5Bbm5vdGF0aW9uGk8KCkFubm90YXRpb24SEAoEcGF0aBgBIAMo", - "BUICEAESEwoLc291cmNlX2ZpbGUYAiABKAkSDQoFYmVnaW4YAyABKAUSCwoD", - "ZW5kGAQgASgFQlgKE2NvbS5nb29nbGUucHJvdG9idWZCEERlc2NyaXB0b3JQ", - "cm90b3NIAVoKZGVzY3JpcHRvcqICA0dQQqoCGkdvb2dsZS5Qcm90b2J1Zi5S", - "ZWZsZWN0aW9u")); + "dGlvbioJCOgHEICAgIACIp4CChNVbmludGVycHJldGVkT3B0aW9uEjsKBG5h", + "bWUYAiADKAsyLS5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlv", + "bi5OYW1lUGFydBIYChBpZGVudGlmaWVyX3ZhbHVlGAMgASgJEhoKEnBvc2l0", + "aXZlX2ludF92YWx1ZRgEIAEoBBIaChJuZWdhdGl2ZV9pbnRfdmFsdWUYBSAB", + "KAMSFAoMZG91YmxlX3ZhbHVlGAYgASgBEhQKDHN0cmluZ192YWx1ZRgHIAEo", + "DBIXCg9hZ2dyZWdhdGVfdmFsdWUYCCABKAkaMwoITmFtZVBhcnQSEQoJbmFt", + "ZV9wYXJ0GAEgAigJEhQKDGlzX2V4dGVuc2lvbhgCIAIoCCLVAQoOU291cmNl", + "Q29kZUluZm8SOgoIbG9jYXRpb24YASADKAsyKC5nb29nbGUucHJvdG9idWYu", + "U291cmNlQ29kZUluZm8uTG9jYXRpb24ahgEKCExvY2F0aW9uEhAKBHBhdGgY", + "ASADKAVCAhABEhAKBHNwYW4YAiADKAVCAhABEhgKEGxlYWRpbmdfY29tbWVu", + "dHMYAyABKAkSGQoRdHJhaWxpbmdfY29tbWVudHMYBCABKAkSIQoZbGVhZGlu", + "Z19kZXRhY2hlZF9jb21tZW50cxgGIAMoCSKnAQoRR2VuZXJhdGVkQ29kZUlu", + "Zm8SQQoKYW5ub3RhdGlvbhgBIAMoCzItLmdvb2dsZS5wcm90b2J1Zi5HZW5l", + "cmF0ZWRDb2RlSW5mby5Bbm5vdGF0aW9uGk8KCkFubm90YXRpb24SEAoEcGF0", + "aBgBIAMoBUICEAESEwoLc291cmNlX2ZpbGUYAiABKAkSDQoFYmVnaW4YAyAB", + "KAUSCwoDZW5kGAQgASgFQlgKE2NvbS5nb29nbGUucHJvdG9idWZCEERlc2Ny", + "aXB0b3JQcm90b3NIAVoKZGVzY3JpcHRvcqICA0dQQqoCGkdvb2dsZS5Qcm90", + "b2J1Zi5SZWZsZWN0aW9u")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { @@ -152,7 +151,7 @@ namespace Google.Protobuf.Reflection { 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", "Deprecated", "CcEnableArenas", "ObjcClassPrefix", "CsharpNamespace", "JavananoUseDeprecatedPackage", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode) }, 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", "Deprecated", "CcEnableArenas", "ObjcClassPrefix", "CsharpNamespace", "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.EnumOptions), global::Google.Protobuf.Reflection.EnumOptions.Parser, new[]{ "AllowAlias", "Deprecated", "UninterpretedOption" }, null, null, null), @@ -1291,7 +1290,7 @@ namespace Google.Protobuf.Reflection { /// <summary>Field number for the "label" field.</summary> public const int LabelFieldNumber = 4; - private global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label label_ = global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label.LABEL_OPTIONAL; + private global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label label_ = 0; public global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label Label { get { return label_; } set { @@ -1301,7 +1300,7 @@ namespace Google.Protobuf.Reflection { /// <summary>Field number for the "type" field.</summary> public const int TypeFieldNumber = 5; - private global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type type_ = global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type.TYPE_DOUBLE; + private global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type type_ = 0; /// <summary> /// 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. @@ -1429,8 +1428,8 @@ namespace Google.Protobuf.Reflection { int hash = 1; if (Name.Length != 0) hash ^= Name.GetHashCode(); if (Number != 0) hash ^= Number.GetHashCode(); - if (Label != global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label.LABEL_OPTIONAL) hash ^= Label.GetHashCode(); - if (Type != global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type.TYPE_DOUBLE) hash ^= Type.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(); @@ -1457,11 +1456,11 @@ namespace Google.Protobuf.Reflection { output.WriteRawTag(24); output.WriteInt32(Number); } - if (Label != global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label.LABEL_OPTIONAL) { + if (Label != 0) { output.WriteRawTag(32); output.WriteEnum((int) Label); } - if (Type != global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type.TYPE_DOUBLE) { + if (Type != 0) { output.WriteRawTag(40); output.WriteEnum((int) Type); } @@ -1495,10 +1494,10 @@ namespace Google.Protobuf.Reflection { if (Number != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number); } - if (Label != global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label.LABEL_OPTIONAL) { + if (Label != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Label); } - if (Type != global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type.TYPE_DOUBLE) { + if (Type != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); } if (TypeName.Length != 0) { @@ -1532,10 +1531,10 @@ namespace Google.Protobuf.Reflection { if (other.Number != 0) { Number = other.Number; } - if (other.Label != global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label.LABEL_OPTIONAL) { + if (other.Label != 0) { Label = other.Label; } - if (other.Type != global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type.TYPE_DOUBLE) { + if (other.Type != 0) { Type = other.Type; } if (other.TypeName.Length != 0) { @@ -1624,59 +1623,59 @@ namespace Google.Protobuf.Reflection { /// 0 is reserved for errors. /// Order is weird for historical reasons. /// </summary> - TYPE_DOUBLE = 1, - TYPE_FLOAT = 2, + [pbr::OriginalName("TYPE_DOUBLE")] Double = 1, + [pbr::OriginalName("TYPE_FLOAT")] Float = 2, /// <summary> /// Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if /// negative values are likely. /// </summary> - TYPE_INT64 = 3, - TYPE_UINT64 = 4, + [pbr::OriginalName("TYPE_INT64")] Int64 = 3, + [pbr::OriginalName("TYPE_UINT64")] Uint64 = 4, /// <summary> /// Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if /// negative values are likely. /// </summary> - TYPE_INT32 = 5, - TYPE_FIXED64 = 6, - TYPE_FIXED32 = 7, - TYPE_BOOL = 8, - TYPE_STRING = 9, + [pbr::OriginalName("TYPE_INT32")] Int32 = 5, + [pbr::OriginalName("TYPE_FIXED64")] Fixed64 = 6, + [pbr::OriginalName("TYPE_FIXED32")] Fixed32 = 7, + [pbr::OriginalName("TYPE_BOOL")] Bool = 8, + [pbr::OriginalName("TYPE_STRING")] String = 9, /// <summary> /// Tag-delimited aggregate. /// </summary> - TYPE_GROUP = 10, + [pbr::OriginalName("TYPE_GROUP")] Group = 10, /// <summary> /// Length-delimited aggregate. /// </summary> - TYPE_MESSAGE = 11, + [pbr::OriginalName("TYPE_MESSAGE")] Message = 11, /// <summary> /// New in version 2. /// </summary> - TYPE_BYTES = 12, - TYPE_UINT32 = 13, - TYPE_ENUM = 14, - TYPE_SFIXED32 = 15, - TYPE_SFIXED64 = 16, + [pbr::OriginalName("TYPE_BYTES")] Bytes = 12, + [pbr::OriginalName("TYPE_UINT32")] Uint32 = 13, + [pbr::OriginalName("TYPE_ENUM")] Enum = 14, + [pbr::OriginalName("TYPE_SFIXED32")] Sfixed32 = 15, + [pbr::OriginalName("TYPE_SFIXED64")] Sfixed64 = 16, /// <summary> /// Uses ZigZag encoding. /// </summary> - TYPE_SINT32 = 17, + [pbr::OriginalName("TYPE_SINT32")] Sint32 = 17, /// <summary> /// Uses ZigZag encoding. /// </summary> - TYPE_SINT64 = 18, + [pbr::OriginalName("TYPE_SINT64")] Sint64 = 18, } internal enum Label { /// <summary> /// 0 is reserved for errors /// </summary> - LABEL_OPTIONAL = 1, - LABEL_REQUIRED = 2, + [pbr::OriginalName("LABEL_OPTIONAL")] Optional = 1, + [pbr::OriginalName("LABEL_REQUIRED")] Required = 2, /// <summary> /// TODO(sanjay): Should we add LABEL_MAP? /// </summary> - LABEL_REPEATED = 3, + [pbr::OriginalName("LABEL_REPEATED")] Repeated = 3, } } @@ -2563,7 +2562,6 @@ namespace Google.Protobuf.Reflection { ccEnableArenas_ = other.ccEnableArenas_; objcClassPrefix_ = other.objcClassPrefix_; csharpNamespace_ = other.csharpNamespace_; - javananoUseDeprecatedPackage_ = other.javananoUseDeprecatedPackage_; uninterpretedOption_ = other.uninterpretedOption_.Clone(); } @@ -2666,7 +2664,7 @@ namespace Google.Protobuf.Reflection { /// <summary>Field number for the "optimize_for" field.</summary> public const int OptimizeForFieldNumber = 9; - private global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode optimizeFor_ = global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode.SPEED; + private global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode optimizeFor_ = 0; public global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode OptimizeFor { get { return optimizeFor_; } set { @@ -2790,21 +2788,6 @@ namespace Google.Protobuf.Reflection { } } - /// <summary>Field number for the "javanano_use_deprecated_package" field.</summary> - public const int JavananoUseDeprecatedPackageFieldNumber = 38; - private bool javananoUseDeprecatedPackage_; - /// <summary> - /// Whether the nano proto compiler should generate in the deprecated non-nano - /// suffixed package. - /// </summary> - [global::System.ObsoleteAttribute()] - public bool JavananoUseDeprecatedPackage { - get { return javananoUseDeprecatedPackage_; } - set { - javananoUseDeprecatedPackage_ = value; - } - } - /// <summary>Field number for the "uninterpreted_option" field.</summary> public const int UninterpretedOptionFieldNumber = 999; private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.UninterpretedOption> _repeated_uninterpretedOption_codec @@ -2842,7 +2825,6 @@ namespace Google.Protobuf.Reflection { if (CcEnableArenas != other.CcEnableArenas) return false; if (ObjcClassPrefix != other.ObjcClassPrefix) return false; if (CsharpNamespace != other.CsharpNamespace) return false; - if (JavananoUseDeprecatedPackage != other.JavananoUseDeprecatedPackage) return false; if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false; return true; } @@ -2854,7 +2836,7 @@ namespace Google.Protobuf.Reflection { if (JavaMultipleFiles != false) hash ^= JavaMultipleFiles.GetHashCode(); if (JavaGenerateEqualsAndHash != false) hash ^= JavaGenerateEqualsAndHash.GetHashCode(); if (JavaStringCheckUtf8 != false) hash ^= JavaStringCheckUtf8.GetHashCode(); - if (OptimizeFor != global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode.SPEED) hash ^= OptimizeFor.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(); @@ -2863,7 +2845,6 @@ namespace Google.Protobuf.Reflection { if (CcEnableArenas != false) hash ^= CcEnableArenas.GetHashCode(); if (ObjcClassPrefix.Length != 0) hash ^= ObjcClassPrefix.GetHashCode(); if (CsharpNamespace.Length != 0) hash ^= CsharpNamespace.GetHashCode(); - if (JavananoUseDeprecatedPackage != false) hash ^= JavananoUseDeprecatedPackage.GetHashCode(); hash ^= uninterpretedOption_.GetHashCode(); return hash; } @@ -2881,7 +2862,7 @@ namespace Google.Protobuf.Reflection { output.WriteRawTag(66); output.WriteString(JavaOuterClassname); } - if (OptimizeFor != global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode.SPEED) { + if (OptimizeFor != 0) { output.WriteRawTag(72); output.WriteEnum((int) OptimizeFor); } @@ -2929,10 +2910,6 @@ namespace Google.Protobuf.Reflection { output.WriteRawTag(170, 2); output.WriteString(CsharpNamespace); } - if (JavananoUseDeprecatedPackage != false) { - output.WriteRawTag(176, 2); - output.WriteBool(JavananoUseDeprecatedPackage); - } uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec); } @@ -2953,7 +2930,7 @@ namespace Google.Protobuf.Reflection { if (JavaStringCheckUtf8 != false) { size += 2 + 1; } - if (OptimizeFor != global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode.SPEED) { + if (OptimizeFor != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) OptimizeFor); } if (GoPackage.Length != 0) { @@ -2980,9 +2957,6 @@ namespace Google.Protobuf.Reflection { if (CsharpNamespace.Length != 0) { size += 2 + pb::CodedOutputStream.ComputeStringSize(CsharpNamespace); } - if (JavananoUseDeprecatedPackage != false) { - size += 2 + 1; - } size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec); return size; } @@ -3006,7 +2980,7 @@ namespace Google.Protobuf.Reflection { if (other.JavaStringCheckUtf8 != false) { JavaStringCheckUtf8 = other.JavaStringCheckUtf8; } - if (other.OptimizeFor != global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode.SPEED) { + if (other.OptimizeFor != 0) { OptimizeFor = other.OptimizeFor; } if (other.GoPackage.Length != 0) { @@ -3033,9 +3007,6 @@ namespace Google.Protobuf.Reflection { if (other.CsharpNamespace.Length != 0) { CsharpNamespace = other.CsharpNamespace; } - if (other.JavananoUseDeprecatedPackage != false) { - JavananoUseDeprecatedPackage = other.JavananoUseDeprecatedPackage; - } uninterpretedOption_.Add(other.uninterpretedOption_); } @@ -3102,10 +3073,6 @@ namespace Google.Protobuf.Reflection { CsharpNamespace = input.ReadString(); break; } - case 304: { - JavananoUseDeprecatedPackage = input.ReadBool(); - break; - } case 7994: { uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec); break; @@ -3125,15 +3092,15 @@ namespace Google.Protobuf.Reflection { /// <summary> /// Generate complete code for parsing, serialization, /// </summary> - SPEED = 1, + [pbr::OriginalName("SPEED")] Speed = 1, /// <summary> /// etc. /// </summary> - CODE_SIZE = 2, + [pbr::OriginalName("CODE_SIZE")] CodeSize = 2, /// <summary> /// Generate code using MessageLite and the lite runtime. /// </summary> - LITE_RUNTIME = 3, + [pbr::OriginalName("LITE_RUNTIME")] LiteRuntime = 3, } } @@ -3436,7 +3403,7 @@ namespace Google.Protobuf.Reflection { /// <summary>Field number for the "ctype" field.</summary> public const int CtypeFieldNumber = 1; - private global::Google.Protobuf.Reflection.FieldOptions.Types.CType ctype_ = global::Google.Protobuf.Reflection.FieldOptions.Types.CType.STRING; + private global::Google.Protobuf.Reflection.FieldOptions.Types.CType ctype_ = 0; /// <summary> /// The ctype option instructs the C++ code generator to use a different /// representation of the field than it normally would. See the specific @@ -3469,7 +3436,7 @@ namespace Google.Protobuf.Reflection { /// <summary>Field number for the "jstype" field.</summary> public const int JstypeFieldNumber = 6; - private global::Google.Protobuf.Reflection.FieldOptions.Types.JSType jstype_ = global::Google.Protobuf.Reflection.FieldOptions.Types.JSType.JS_NORMAL; + private global::Google.Protobuf.Reflection.FieldOptions.Types.JSType jstype_ = 0; /// <summary> /// 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 @@ -3591,9 +3558,9 @@ namespace Google.Protobuf.Reflection { public override int GetHashCode() { int hash = 1; - if (Ctype != global::Google.Protobuf.Reflection.FieldOptions.Types.CType.STRING) hash ^= Ctype.GetHashCode(); + if (Ctype != 0) hash ^= Ctype.GetHashCode(); if (Packed != false) hash ^= Packed.GetHashCode(); - if (Jstype != global::Google.Protobuf.Reflection.FieldOptions.Types.JSType.JS_NORMAL) hash ^= Jstype.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(); @@ -3606,7 +3573,7 @@ namespace Google.Protobuf.Reflection { } public void WriteTo(pb::CodedOutputStream output) { - if (Ctype != global::Google.Protobuf.Reflection.FieldOptions.Types.CType.STRING) { + if (Ctype != 0) { output.WriteRawTag(8); output.WriteEnum((int) Ctype); } @@ -3622,7 +3589,7 @@ namespace Google.Protobuf.Reflection { output.WriteRawTag(40); output.WriteBool(Lazy); } - if (Jstype != global::Google.Protobuf.Reflection.FieldOptions.Types.JSType.JS_NORMAL) { + if (Jstype != 0) { output.WriteRawTag(48); output.WriteEnum((int) Jstype); } @@ -3635,13 +3602,13 @@ namespace Google.Protobuf.Reflection { public int CalculateSize() { int size = 0; - if (Ctype != global::Google.Protobuf.Reflection.FieldOptions.Types.CType.STRING) { + if (Ctype != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Ctype); } if (Packed != false) { size += 1 + 1; } - if (Jstype != global::Google.Protobuf.Reflection.FieldOptions.Types.JSType.JS_NORMAL) { + if (Jstype != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Jstype); } if (Lazy != false) { @@ -3661,13 +3628,13 @@ namespace Google.Protobuf.Reflection { if (other == null) { return; } - if (other.Ctype != global::Google.Protobuf.Reflection.FieldOptions.Types.CType.STRING) { + if (other.Ctype != 0) { Ctype = other.Ctype; } if (other.Packed != false) { Packed = other.Packed; } - if (other.Jstype != global::Google.Protobuf.Reflection.FieldOptions.Types.JSType.JS_NORMAL) { + if (other.Jstype != 0) { Jstype = other.Jstype; } if (other.Lazy != false) { @@ -3729,24 +3696,24 @@ namespace Google.Protobuf.Reflection { /// <summary> /// Default mode. /// </summary> - STRING = 0, - CORD = 1, - STRING_PIECE = 2, + [pbr::OriginalName("STRING")] String = 0, + [pbr::OriginalName("CORD")] Cord = 1, + [pbr::OriginalName("STRING_PIECE")] StringPiece = 2, } internal enum JSType { /// <summary> /// Use the default type. /// </summary> - JS_NORMAL = 0, + [pbr::OriginalName("JS_NORMAL")] JsNormal = 0, /// <summary> /// Use JavaScript strings. /// </summary> - JS_STRING = 1, + [pbr::OriginalName("JS_STRING")] JsString = 1, /// <summary> /// Use JavaScript numbers. /// </summary> - JS_NUMBER = 2, + [pbr::OriginalName("JS_NUMBER")] JsNumber = 2, } } diff --git a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs index de6e5717..6c6f6ee0 100644 --- a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs @@ -133,41 +133,41 @@ namespace Google.Protobuf.Reflection { switch (type) { - case FieldDescriptorProto.Types.Type.TYPE_DOUBLE: + case FieldDescriptorProto.Types.Type.Double: return FieldType.Double; - case FieldDescriptorProto.Types.Type.TYPE_FLOAT: + case FieldDescriptorProto.Types.Type.Float: return FieldType.Float; - case FieldDescriptorProto.Types.Type.TYPE_INT64: + case FieldDescriptorProto.Types.Type.Int64: return FieldType.Int64; - case FieldDescriptorProto.Types.Type.TYPE_UINT64: + case FieldDescriptorProto.Types.Type.Uint64: return FieldType.UInt64; - case FieldDescriptorProto.Types.Type.TYPE_INT32: + case FieldDescriptorProto.Types.Type.Int32: return FieldType.Int32; - case FieldDescriptorProto.Types.Type.TYPE_FIXED64: + case FieldDescriptorProto.Types.Type.Fixed64: return FieldType.Fixed64; - case FieldDescriptorProto.Types.Type.TYPE_FIXED32: + case FieldDescriptorProto.Types.Type.Fixed32: return FieldType.Fixed32; - case FieldDescriptorProto.Types.Type.TYPE_BOOL: + case FieldDescriptorProto.Types.Type.Bool: return FieldType.Bool; - case FieldDescriptorProto.Types.Type.TYPE_STRING: + case FieldDescriptorProto.Types.Type.String: return FieldType.String; - case FieldDescriptorProto.Types.Type.TYPE_GROUP: + case FieldDescriptorProto.Types.Type.Group: return FieldType.Group; - case FieldDescriptorProto.Types.Type.TYPE_MESSAGE: + case FieldDescriptorProto.Types.Type.Message: return FieldType.Message; - case FieldDescriptorProto.Types.Type.TYPE_BYTES: + case FieldDescriptorProto.Types.Type.Bytes: return FieldType.Bytes; - case FieldDescriptorProto.Types.Type.TYPE_UINT32: + case FieldDescriptorProto.Types.Type.Uint32: return FieldType.UInt32; - case FieldDescriptorProto.Types.Type.TYPE_ENUM: + case FieldDescriptorProto.Types.Type.Enum: return FieldType.Enum; - case FieldDescriptorProto.Types.Type.TYPE_SFIXED32: + case FieldDescriptorProto.Types.Type.Sfixed32: return FieldType.SFixed32; - case FieldDescriptorProto.Types.Type.TYPE_SFIXED64: + case FieldDescriptorProto.Types.Type.Sfixed64: return FieldType.SFixed64; - case FieldDescriptorProto.Types.Type.TYPE_SINT32: + case FieldDescriptorProto.Types.Type.Sint32: return FieldType.SInt32; - case FieldDescriptorProto.Types.Type.TYPE_SINT64: + case FieldDescriptorProto.Types.Type.Sint64: return FieldType.SInt64; default: throw new ArgumentException("Invalid type specified"); @@ -177,7 +177,7 @@ namespace Google.Protobuf.Reflection /// <summary> /// Returns <c>true</c> if this field is a repeated field; <c>false</c> otherwise. /// </summary> - public bool IsRepeated => Proto.Label == FieldDescriptorProto.Types.Label.LABEL_REPEATED; + public bool IsRepeated => Proto.Label == FieldDescriptorProto.Types.Label.Repeated; /// <summary> /// Returns <c>true</c> if this field is a map field; <c>false</c> otherwise. diff --git a/csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs b/csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs new file mode 100644 index 00000000..27f9ab98 --- /dev/null +++ b/csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs @@ -0,0 +1,58 @@ +#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.Reflection +{ + /// <summary> + /// Specifies the original name (in the .proto file) of a named element, + /// such as an enum value. + /// </summary> + [AttributeUsage(AttributeTargets.Field)] + public class OriginalNameAttribute : Attribute + { + /// <summary> + /// The name of the element in the .proto file. + /// </summary> + public string Name { get; set; } + + /// <summary> + /// Constructs a new attribute instance for the given name. + /// </summary> + /// <param name="name">The name of the element in the .proto file.</param> + public OriginalNameAttribute(string name) + { + Name = ProtoPreconditions.CheckNotNull(name, nameof(name)); + } + } +}
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs index 48cd99a1..871a383f 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs @@ -24,9 +24,10 @@ namespace Google.Protobuf.WellKnownTypes { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "Chlnb29nbGUvcHJvdG9idWYvYW55LnByb3RvEg9nb29nbGUucHJvdG9idWYi", - "JgoDQW55EhAKCHR5cGVfdXJsGAEgASgJEg0KBXZhbHVlGAIgASgMQksKE2Nv", - "bS5nb29nbGUucHJvdG9idWZCCEFueVByb3RvUAGgAQGiAgNHUEKqAh5Hb29n", - "bGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw==")); + "JgoDQW55EhAKCHR5cGVfdXJsGAEgASgJEg0KBXZhbHVlGAIgASgMQnIKE2Nv", + "bS5nb29nbGUucHJvdG9idWZCCEFueVByb3RvUAFaJWdpdGh1Yi5jb20vZ29s", + "YW5nL3Byb3RvYnVmL3B0eXBlcy9hbnmgAQGiAgNHUEKqAh5Hb29nbGUuUHJv", + "dG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { @@ -38,8 +39,36 @@ namespace Google.Protobuf.WellKnownTypes { } #region Messages /// <summary> - /// `Any` contains an arbitrary serialized message along with a URL - /// that describes the type of the serialized message. + /// `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); + /// } + /// + /// 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 /// ==== @@ -102,7 +131,7 @@ namespace Google.Protobuf.WellKnownTypes { private string typeUrl_ = ""; /// <summary> /// A URL/resource name whose content describes the type of the - /// serialized message. + /// serialized protocol buffer message. /// /// For URLs which use the schema `http`, `https`, or no schema, the /// following restrictions and interpretations apply: @@ -110,6 +139,8 @@ namespace Google.Protobuf.WellKnownTypes { /// * If no schema 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 @@ -132,7 +163,7 @@ namespace Google.Protobuf.WellKnownTypes { public const int ValueFieldNumber = 2; private pb::ByteString value_ = pb::ByteString.Empty; /// <summary> - /// Must be valid serialized data of the above specified type. + /// Must be a valid serialized protocol buffer of the above specified type. /// </summary> public pb::ByteString Value { get { return value_; } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs index de7aea3a..e568a2c9 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs @@ -185,7 +185,7 @@ namespace Google.Protobuf.WellKnownTypes { /// <summary>Field number for the "syntax" field.</summary> public const int SyntaxFieldNumber = 7; - private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2; + private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = 0; /// <summary> /// The source syntax of the service. /// </summary> @@ -225,7 +225,7 @@ namespace Google.Protobuf.WellKnownTypes { if (Version.Length != 0) hash ^= Version.GetHashCode(); if (sourceContext_ != null) hash ^= SourceContext.GetHashCode(); hash ^= mixins_.GetHashCode(); - if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) hash ^= Syntax.GetHashCode(); + if (Syntax != 0) hash ^= Syntax.GetHashCode(); return hash; } @@ -249,7 +249,7 @@ namespace Google.Protobuf.WellKnownTypes { output.WriteMessage(SourceContext); } mixins_.WriteTo(output, _repeated_mixins_codec); - if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) { + if (Syntax != 0) { output.WriteRawTag(56); output.WriteEnum((int) Syntax); } @@ -269,7 +269,7 @@ namespace Google.Protobuf.WellKnownTypes { size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContext); } size += mixins_.CalculateSize(_repeated_mixins_codec); - if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) { + if (Syntax != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax); } return size; @@ -294,7 +294,7 @@ namespace Google.Protobuf.WellKnownTypes { SourceContext.MergeFrom(other.SourceContext); } mixins_.Add(other.mixins_); - if (other.Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) { + if (other.Syntax != 0) { Syntax = other.Syntax; } } @@ -458,7 +458,7 @@ namespace Google.Protobuf.WellKnownTypes { /// <summary>Field number for the "syntax" field.</summary> public const int SyntaxFieldNumber = 7; - private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2; + private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = 0; /// <summary> /// The source syntax of this method. /// </summary> @@ -498,7 +498,7 @@ namespace Google.Protobuf.WellKnownTypes { if (ResponseTypeUrl.Length != 0) hash ^= ResponseTypeUrl.GetHashCode(); if (ResponseStreaming != false) hash ^= ResponseStreaming.GetHashCode(); hash ^= options_.GetHashCode(); - if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) hash ^= Syntax.GetHashCode(); + if (Syntax != 0) hash ^= Syntax.GetHashCode(); return hash; } @@ -528,7 +528,7 @@ namespace Google.Protobuf.WellKnownTypes { output.WriteBool(ResponseStreaming); } options_.WriteTo(output, _repeated_options_codec); - if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) { + if (Syntax != 0) { output.WriteRawTag(56); output.WriteEnum((int) Syntax); } @@ -552,7 +552,7 @@ namespace Google.Protobuf.WellKnownTypes { size += 1 + 1; } size += options_.CalculateSize(_repeated_options_codec); - if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) { + if (Syntax != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax); } return size; @@ -578,7 +578,7 @@ namespace Google.Protobuf.WellKnownTypes { ResponseStreaming = other.ResponseStreaming; } options_.Add(other.options_); - if (other.Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) { + if (other.Syntax != 0) { Syntax = other.Syntax; } } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs index 73e221d4..f17358f4 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs @@ -25,9 +25,10 @@ namespace Google.Protobuf.WellKnownTypes { string.Concat( "Ch5nb29nbGUvcHJvdG9idWYvZHVyYXRpb24ucHJvdG8SD2dvb2dsZS5wcm90", "b2J1ZiIqCghEdXJhdGlvbhIPCgdzZWNvbmRzGAEgASgDEg0KBW5hbm9zGAIg", - "ASgFQlAKE2NvbS5nb29nbGUucHJvdG9idWZCDUR1cmF0aW9uUHJvdG9QAaAB", - "AaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJv", - "dG8z")); + "ASgFQnwKE2NvbS5nb29nbGUucHJvdG9idWZCDUR1cmF0aW9uUHJvdG9QAVoq", + "Z2l0aHViLmNvbS9nb2xhbmcvcHJvdG9idWYvcHR5cGVzL2R1cmF0aW9uoAEB", + "ogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZwcm90", + "bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs index 6cad4124..e08ea240 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs @@ -24,9 +24,10 @@ namespace Google.Protobuf.WellKnownTypes { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "Chtnb29nbGUvcHJvdG9idWYvZW1wdHkucHJvdG8SD2dvb2dsZS5wcm90b2J1", - "ZiIHCgVFbXB0eUJQChNjb20uZ29vZ2xlLnByb3RvYnVmQgpFbXB0eVByb3Rv", - "UAGgAQH4AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlw", - "ZXNiBnByb3RvMw==")); + "ZiIHCgVFbXB0eUJ5ChNjb20uZ29vZ2xlLnByb3RvYnVmQgpFbXB0eVByb3Rv", + "UAFaJ2dpdGh1Yi5jb20vZ29sYW5nL3Byb3RvYnVmL3B0eXBlcy9lbXB0eaAB", + "AfgBAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IG", + "cHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs index 2ba2b96f..6f0a64d6 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs @@ -86,7 +86,7 @@ namespace Google.Protobuf.WellKnownTypes { /// operation applies to all fields (as if a FieldMask of all fields /// had been specified). /// - /// Note that a field mask does not necessarily applies to the + /// 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 @@ -159,6 +159,33 @@ namespace Google.Protobuf.WellKnownTypes { /// { /// 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. /// </summary> [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public sealed partial class FieldMask : pb::IMessage<FieldMask> { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs index 8e2ce8cf..edc8940d 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs @@ -34,9 +34,10 @@ namespace Google.Protobuf.WellKnownTypes { "ABIwCgpsaXN0X3ZhbHVlGAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLkxpc3RW", "YWx1ZUgAQgYKBGtpbmQiMwoJTGlzdFZhbHVlEiYKBnZhbHVlcxgBIAMoCzIW", "Lmdvb2dsZS5wcm90b2J1Zi5WYWx1ZSobCglOdWxsVmFsdWUSDgoKTlVMTF9W", - "QUxVRRAAQk4KE2NvbS5nb29nbGUucHJvdG9idWZCC1N0cnVjdFByb3RvUAGg", - "AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnBy", - "b3RvMw==")); + "QUxVRRAAQoEBChNjb20uZ29vZ2xlLnByb3RvYnVmQgtTdHJ1Y3RQcm90b1AB", + "WjFnaXRodWIuY29tL2dvbGFuZy9wcm90b2J1Zi9wdHlwZXMvc3RydWN0O3N0", + "cnVjdHBioAEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5", + "cGVzYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.NullValue), }, new pbr::GeneratedClrTypeInfo[] { @@ -59,7 +60,7 @@ namespace Google.Protobuf.WellKnownTypes { /// <summary> /// Null value. /// </summary> - NULL_VALUE = 0, + [pbr::OriginalName("NULL_VALUE")] NullValue = 0, } #endregion @@ -108,7 +109,7 @@ namespace Google.Protobuf.WellKnownTypes { = new pbc::MapField<string, global::Google.Protobuf.WellKnownTypes.Value>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Value.Parser), 10); private readonly pbc::MapField<string, global::Google.Protobuf.WellKnownTypes.Value> fields_ = new pbc::MapField<string, global::Google.Protobuf.WellKnownTypes.Value>(); /// <summary> - /// Map of dynamically typed values. + /// Unordered map of dynamically typed values. /// </summary> public pbc::MapField<string, global::Google.Protobuf.WellKnownTypes.Value> Fields { get { return fields_; } @@ -234,7 +235,7 @@ namespace Google.Protobuf.WellKnownTypes { /// Represents a null value. /// </summary> public global::Google.Protobuf.WellKnownTypes.NullValue NullValue { - get { return kindCase_ == KindOneofCase.NullValue ? (global::Google.Protobuf.WellKnownTypes.NullValue) kind_ : global::Google.Protobuf.WellKnownTypes.NullValue.NULL_VALUE; } + get { return kindCase_ == KindOneofCase.NullValue ? (global::Google.Protobuf.WellKnownTypes.NullValue) kind_ : 0; } set { kind_ = value; kindCase_ = KindOneofCase.NullValue; diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs index 318b0f61..053b88bd 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs @@ -25,9 +25,10 @@ namespace Google.Protobuf.WellKnownTypes { string.Concat( "Ch9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1wLnByb3RvEg9nb29nbGUucHJv", "dG9idWYiKwoJVGltZXN0YW1wEg8KB3NlY29uZHMYASABKAMSDQoFbmFub3MY", - "AiABKAVCVAoTY29tLmdvb2dsZS5wcm90b2J1ZkIOVGltZXN0YW1wUHJvdG9Q", - "AaABAfgBAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBl", - "c2IGcHJvdG8z")); + "AiABKAVCgQEKE2NvbS5nb29nbGUucHJvdG9idWZCDlRpbWVzdGFtcFByb3Rv", + "UAFaK2dpdGh1Yi5jb20vZ29sYW5nL3Byb3RvYnVmL3B0eXBlcy90aW1lc3Rh", + "bXCgAQH4AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlw", + "ZXNiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs index 8faa1d1c..657c2464 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs @@ -79,11 +79,11 @@ namespace Google.Protobuf.WellKnownTypes { /// <summary> /// Syntax `proto2`. /// </summary> - SYNTAX_PROTO2 = 0, + [pbr::OriginalName("SYNTAX_PROTO2")] Proto2 = 0, /// <summary> /// Syntax `proto3`. /// </summary> - SYNTAX_PROTO3 = 1, + [pbr::OriginalName("SYNTAX_PROTO3")] Proto3 = 1, } #endregion @@ -188,7 +188,7 @@ namespace Google.Protobuf.WellKnownTypes { /// <summary>Field number for the "syntax" field.</summary> public const int SyntaxFieldNumber = 6; - private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2; + private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = 0; /// <summary> /// The source syntax. /// </summary> @@ -226,7 +226,7 @@ namespace Google.Protobuf.WellKnownTypes { hash ^= oneofs_.GetHashCode(); hash ^= options_.GetHashCode(); if (sourceContext_ != null) hash ^= SourceContext.GetHashCode(); - if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) hash ^= Syntax.GetHashCode(); + if (Syntax != 0) hash ^= Syntax.GetHashCode(); return hash; } @@ -246,7 +246,7 @@ namespace Google.Protobuf.WellKnownTypes { output.WriteRawTag(42); output.WriteMessage(SourceContext); } - if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) { + if (Syntax != 0) { output.WriteRawTag(48); output.WriteEnum((int) Syntax); } @@ -263,7 +263,7 @@ namespace Google.Protobuf.WellKnownTypes { if (sourceContext_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContext); } - if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) { + if (Syntax != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax); } return size; @@ -285,7 +285,7 @@ namespace Google.Protobuf.WellKnownTypes { } SourceContext.MergeFrom(other.SourceContext); } - if (other.Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) { + if (other.Syntax != 0) { Syntax = other.Syntax; } } @@ -371,7 +371,7 @@ namespace Google.Protobuf.WellKnownTypes { /// <summary>Field number for the "kind" field.</summary> public const int KindFieldNumber = 1; - private global::Google.Protobuf.WellKnownTypes.Field.Types.Kind kind_ = global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TYPE_UNKNOWN; + private global::Google.Protobuf.WellKnownTypes.Field.Types.Kind kind_ = 0; /// <summary> /// The field type. /// </summary> @@ -384,7 +384,7 @@ namespace Google.Protobuf.WellKnownTypes { /// <summary>Field number for the "cardinality" field.</summary> public const int CardinalityFieldNumber = 2; - private global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality cardinality_ = global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.CARDINALITY_UNKNOWN; + private global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality cardinality_ = 0; /// <summary> /// The field cardinality. /// </summary> @@ -526,8 +526,8 @@ namespace Google.Protobuf.WellKnownTypes { public override int GetHashCode() { int hash = 1; - if (Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TYPE_UNKNOWN) hash ^= Kind.GetHashCode(); - if (Cardinality != global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.CARDINALITY_UNKNOWN) hash ^= Cardinality.GetHashCode(); + if (Kind != 0) hash ^= Kind.GetHashCode(); + if (Cardinality != 0) hash ^= Cardinality.GetHashCode(); if (Number != 0) hash ^= Number.GetHashCode(); if (Name.Length != 0) hash ^= Name.GetHashCode(); if (TypeUrl.Length != 0) hash ^= TypeUrl.GetHashCode(); @@ -544,11 +544,11 @@ namespace Google.Protobuf.WellKnownTypes { } public void WriteTo(pb::CodedOutputStream output) { - if (Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TYPE_UNKNOWN) { + if (Kind != 0) { output.WriteRawTag(8); output.WriteEnum((int) Kind); } - if (Cardinality != global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.CARDINALITY_UNKNOWN) { + if (Cardinality != 0) { output.WriteRawTag(16); output.WriteEnum((int) Cardinality); } @@ -585,10 +585,10 @@ namespace Google.Protobuf.WellKnownTypes { public int CalculateSize() { int size = 0; - if (Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TYPE_UNKNOWN) { + if (Kind != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Kind); } - if (Cardinality != global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.CARDINALITY_UNKNOWN) { + if (Cardinality != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Cardinality); } if (Number != 0) { @@ -620,10 +620,10 @@ namespace Google.Protobuf.WellKnownTypes { if (other == null) { return; } - if (other.Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TYPE_UNKNOWN) { + if (other.Kind != 0) { Kind = other.Kind; } - if (other.Cardinality != global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.CARDINALITY_UNKNOWN) { + if (other.Cardinality != 0) { Cardinality = other.Cardinality; } if (other.Number != 0) { @@ -712,79 +712,79 @@ namespace Google.Protobuf.WellKnownTypes { /// <summary> /// Field type unknown. /// </summary> - TYPE_UNKNOWN = 0, + [pbr::OriginalName("TYPE_UNKNOWN")] TypeUnknown = 0, /// <summary> /// Field type double. /// </summary> - TYPE_DOUBLE = 1, + [pbr::OriginalName("TYPE_DOUBLE")] TypeDouble = 1, /// <summary> /// Field type float. /// </summary> - TYPE_FLOAT = 2, + [pbr::OriginalName("TYPE_FLOAT")] TypeFloat = 2, /// <summary> /// Field type int64. /// </summary> - TYPE_INT64 = 3, + [pbr::OriginalName("TYPE_INT64")] TypeInt64 = 3, /// <summary> /// Field type uint64. /// </summary> - TYPE_UINT64 = 4, + [pbr::OriginalName("TYPE_UINT64")] TypeUint64 = 4, /// <summary> /// Field type int32. /// </summary> - TYPE_INT32 = 5, + [pbr::OriginalName("TYPE_INT32")] TypeInt32 = 5, /// <summary> /// Field type fixed64. /// </summary> - TYPE_FIXED64 = 6, + [pbr::OriginalName("TYPE_FIXED64")] TypeFixed64 = 6, /// <summary> /// Field type fixed32. /// </summary> - TYPE_FIXED32 = 7, + [pbr::OriginalName("TYPE_FIXED32")] TypeFixed32 = 7, /// <summary> /// Field type bool. /// </summary> - TYPE_BOOL = 8, + [pbr::OriginalName("TYPE_BOOL")] TypeBool = 8, /// <summary> /// Field type string. /// </summary> - TYPE_STRING = 9, + [pbr::OriginalName("TYPE_STRING")] TypeString = 9, /// <summary> /// Field type group. Proto2 syntax only, and deprecated. /// </summary> - TYPE_GROUP = 10, + [pbr::OriginalName("TYPE_GROUP")] TypeGroup = 10, /// <summary> /// Field type message. /// </summary> - TYPE_MESSAGE = 11, + [pbr::OriginalName("TYPE_MESSAGE")] TypeMessage = 11, /// <summary> /// Field type bytes. /// </summary> - TYPE_BYTES = 12, + [pbr::OriginalName("TYPE_BYTES")] TypeBytes = 12, /// <summary> /// Field type uint32. /// </summary> - TYPE_UINT32 = 13, + [pbr::OriginalName("TYPE_UINT32")] TypeUint32 = 13, /// <summary> /// Field type enum. /// </summary> - TYPE_ENUM = 14, + [pbr::OriginalName("TYPE_ENUM")] TypeEnum = 14, /// <summary> /// Field type sfixed32. /// </summary> - TYPE_SFIXED32 = 15, + [pbr::OriginalName("TYPE_SFIXED32")] TypeSfixed32 = 15, /// <summary> /// Field type sfixed64. /// </summary> - TYPE_SFIXED64 = 16, + [pbr::OriginalName("TYPE_SFIXED64")] TypeSfixed64 = 16, /// <summary> /// Field type sint32. /// </summary> - TYPE_SINT32 = 17, + [pbr::OriginalName("TYPE_SINT32")] TypeSint32 = 17, /// <summary> /// Field type sint64. /// </summary> - TYPE_SINT64 = 18, + [pbr::OriginalName("TYPE_SINT64")] TypeSint64 = 18, } /// <summary> @@ -794,19 +794,19 @@ namespace Google.Protobuf.WellKnownTypes { /// <summary> /// For fields with unknown cardinality. /// </summary> - CARDINALITY_UNKNOWN = 0, + [pbr::OriginalName("CARDINALITY_UNKNOWN")] Unknown = 0, /// <summary> /// For optional fields. /// </summary> - CARDINALITY_OPTIONAL = 1, + [pbr::OriginalName("CARDINALITY_OPTIONAL")] Optional = 1, /// <summary> /// For required fields. Proto2 syntax only. /// </summary> - CARDINALITY_REQUIRED = 2, + [pbr::OriginalName("CARDINALITY_REQUIRED")] Required = 2, /// <summary> /// For repeated fields. /// </summary> - CARDINALITY_REPEATED = 3, + [pbr::OriginalName("CARDINALITY_REPEATED")] Repeated = 3, } } @@ -900,7 +900,7 @@ namespace Google.Protobuf.WellKnownTypes { /// <summary>Field number for the "syntax" field.</summary> public const int SyntaxFieldNumber = 5; - private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2; + private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = 0; /// <summary> /// The source syntax. /// </summary> @@ -936,7 +936,7 @@ namespace Google.Protobuf.WellKnownTypes { hash ^= enumvalue_.GetHashCode(); hash ^= options_.GetHashCode(); if (sourceContext_ != null) hash ^= SourceContext.GetHashCode(); - if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) hash ^= Syntax.GetHashCode(); + if (Syntax != 0) hash ^= Syntax.GetHashCode(); return hash; } @@ -955,7 +955,7 @@ namespace Google.Protobuf.WellKnownTypes { output.WriteRawTag(34); output.WriteMessage(SourceContext); } - if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) { + if (Syntax != 0) { output.WriteRawTag(40); output.WriteEnum((int) Syntax); } @@ -971,7 +971,7 @@ namespace Google.Protobuf.WellKnownTypes { if (sourceContext_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContext); } - if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) { + if (Syntax != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax); } return size; @@ -992,7 +992,7 @@ namespace Google.Protobuf.WellKnownTypes { } SourceContext.MergeFrom(other.SourceContext); } - if (other.Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) { + if (other.Syntax != 0) { Syntax = other.Syntax; } } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs index d6796d1a..c8867d0e 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs @@ -29,10 +29,10 @@ namespace Google.Protobuf.WellKnownTypes { "KAMiHAoLVUludDY0VmFsdWUSDQoFdmFsdWUYASABKAQiGwoKSW50MzJWYWx1", "ZRINCgV2YWx1ZRgBIAEoBSIcCgtVSW50MzJWYWx1ZRINCgV2YWx1ZRgBIAEo", "DSIaCglCb29sVmFsdWUSDQoFdmFsdWUYASABKAgiHAoLU3RyaW5nVmFsdWUS", - "DQoFdmFsdWUYASABKAkiGwoKQnl0ZXNWYWx1ZRINCgV2YWx1ZRgBIAEoDEJT", - "ChNjb20uZ29vZ2xlLnByb3RvYnVmQg1XcmFwcGVyc1Byb3RvUAGgAQH4AQGi", - "AgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3Rv", - "Mw==")); + "DQoFdmFsdWUYASABKAkiGwoKQnl0ZXNWYWx1ZRINCgV2YWx1ZRgBIAEoDEJ/", + "ChNjb20uZ29vZ2xlLnByb3RvYnVmQg1XcmFwcGVyc1Byb3RvUAFaKmdpdGh1", + "Yi5jb20vZ29sYW5nL3Byb3RvYnVmL3B0eXBlcy93cmFwcGVyc6ABAfgBAaIC", + "A0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { diff --git a/docs/swift/DesignDoc.md b/docs/swift/DesignDoc.md new file mode 100644 index 00000000..364a4d3f --- /dev/null +++ b/docs/swift/DesignDoc.md @@ -0,0 +1,674 @@ +# Protocol Buffers in Swift + +## Objective + +This document describes the user-facing API and internal implementation of +proto2 and proto3 messages in Apple’s Swift programming language. + +One of the key goals of protobufs is to provide idiomatic APIs for each +language. In that vein, **interoperability with Objective-C is a non-goal of +this proposal.** Protobuf users who need to pass messages between Objective-C +and Swift code in the same application should use the existing Objective-C proto +library. The goal of the effort described here is to provide an API for protobuf +messages that uses features specific to Swift—optional types, algebraic +enumerated types, value types, and so forth—in a natural way that will delight, +rather than surprise, users of the language. + +## Naming + +* By convention, both typical protobuf message names and Swift structs/classes + are `UpperCamelCase`, so for most messages, the name of a message can be the + same as the name of its generated type. (However, see the discussion below + about prefixes under [Packages](#packages).) + +* Enum cases in protobufs typically are `UPPERCASE_WITH_UNDERSCORES`, whereas + in Swift they are `lowerCamelCase` (as of the Swift 3 API design + guidelines). We will transform the names to match Swift convention, using + a whitelist similar to the Objective-C compiler plugin to handle commonly + used acronyms. + +* Typical fields in proto messages are `lowercase_with_underscores`, while in + Swift they are `lowerCamelCase`. We will transform the names to match + Swift convention by removing the underscores and uppercasing the subsequent + letter. + +## Swift reserved words + +Swift has a large set of reserved words—some always reserved and some +contextually reserved (that is, they can be used as identifiers in contexts +where they would not be confused). As of Swift 2.2, the set of always-reserved +words is: + +``` +_, #available, #column, #else, #elseif, #endif, #file, #function, #if, #line, +#selector, as, associatedtype, break, case, catch, class, continue, default, +defer, deinit, do, dynamicType, else, enum, extension, fallthrough, false, for, +func, guard, if, import, in, init, inout, internal, is, let, nil, operator, +private, protocol, public, repeat, rethrows, return, self, Self, static, +struct, subscript, super, switch, throw, throws, true, try, typealias, var, +where, while +``` + +The set of contextually reserved words is: + +``` +associativity, convenience, dynamic, didSet, final, get, infix, indirect, +lazy, left, mutating, none, nonmutating, optional, override, postfix, +precedence, prefix, Protocol, required, right, set, Type, unowned, weak, +willSet +``` + +It is possible to use any reserved word as an identifier by escaping it with +backticks (for example, ``let `class` = 5``). Other name-mangling schemes would +require us to transform the names themselves (for example, by appending an +underscore), which requires us to then ensure that the new name does not collide +with something else in the same namespace. + +While the backtick feature may not be widely known by all Swift developers, a +small amount of user education can address this and it seems like the best +approach. We can unconditionally surround all property names with backticks to +simplify generation. + +Some remapping will still be required, though, to avoid collisions between +generated properties and the names of methods and properties defined in the base +protocol/implementation of messages. + +# Features of Protocol Buffers + +This section describes how the features of the protocol buffer syntaxes (proto2 +and proto3) map to features in Swift—what the code generated from a proto will +look like, and how it will be implemented in the underlying library. + +## Packages + +Modules are the main form of namespacing in Swift, but they are not declared +using syntactic constructs like namespaces in C++ or packages in Java. Instead, +they are tied to build targets in Xcode (or, in the future with open-source +Swift, declarations in a Swift Package Manager manifest). They also do not +easily support nesting submodules (Clang module maps support this, but pure +Swift does not yet provide a way to define submodules). + +We will generate types with fully-qualified underscore-delimited names. For +example, a message `Baz` in package `foo.bar` would generate a struct named +`Foo_Bar_Baz`. For each fully-qualified proto message, there will be exactly one +unique type symbol emitted in the generated binary. + +Users are likely to balk at the ugliness of underscore-delimited names for every +generated type. To improve upon this situation, we will add a new string file +level option, `swift_package_typealias`, that can be added to `.proto` files. +When present, this will cause `typealias`es to be added to the generated Swift +messages that replace the package name prefix with the provided string. For +example, the following `.proto` file: + +```protobuf +option swift_package_typealias = "FBP"; +package foo.bar; + +message Baz { + // Message fields +} +``` + +would generate the following Swift source: + +```swift +public struct Foo_Bar_Baz { + // Message fields and other methods +} + +typealias FBPBaz = Foo_Bar_Baz +``` + +It should be noted that this type alias is recorded in the generated +`.swiftmodule` so that code importing the module can refer to it, but it does +not cause a new symbol to be generated in the compiled binary (i.e., we do not +risk compiled size bloat by adding `typealias`es for every type). + +Other strategies to handle packages that were considered and rejected can be +found in [Appendix A](#appendix-a-rejected-strategies-to-handle-packages). + +## Messages + +Proto messages are natural value types and we will generate messages as structs +instead of classes. Users will benefit from Swift’s built-in behavior with +regard to mutability. We will define a `ProtoMessage` protocol that defines the +common methods and properties for all messages (such as serialization) and also +lets users treat messages polymorphically. Any shared method implementations +that do not differ between individual messages can be implemented in a protocol +extension. + +The backing storage itself for fields of a message will be managed by a +`ProtoFieldStorage` type that uses an internal dictionary keyed by field number, +and whose values are the value of the field with that number (up-cast to Swift’s +`Any` type). This class will provide type-safe getters and setters so that +generated messages can manipulate this storage, and core serialization logic +will live here as well. Furthermore, factoring the storage out into a separate +type, rather than inlining the fields as stored properties in the message +itself, lets us implement copy-on-write efficiently to support passing around +large messages. (Furthermore, because the messages themselves are value types, +inlining fields is not possible if the fields are submessages of the same type, +or a type that eventually includes a submessage of the same type.) + +### Required fields (proto2 only) + +Required fields in proto2 messages seem like they could be naturally represented +by non-optional properties in Swift, but this presents some problems/concerns. + +Serialization APIs permit partial serialization, which allows required fields to +remain unset. Furthermore, other language APIs still provide `has*` and `clear*` +methods for required fields, and knowing whether a property has a value when the +message is in memory is still useful. + +For example, an e-mail draft message may have the “to” address required on the +wire, but when the user constructs it in memory, it doesn’t make sense to force +a value until they provide one. We only want to force a value to be present when +the message is serialized to the wire. Using non-optional properties prevents +this use case, and makes client usage awkward because the user would be forced +to select a sentinel or placeholder value for any required fields at the time +the message was created. + +### Default values + +In proto2, fields can have a default value specified that may be a value other +than the default value for its corresponding language type (for example, a +default value of 5 instead of 0 for an integer). When reading a field that is +not explicitly set, the user expects to get that value. This makes Swift +optionals (i.e., `Foo?`) unsuitable for fields in general. Unfortunately, we +cannot implement our own “enhanced optional” type without severely complicating +usage (Swift’s use of type inference and its lack of implicit conversions would +require manual unwrapping of every property value). + +Instead, we can use **implicitly unwrapped optionals.** For example, a property +generated for a field of type `int32` would have Swift type `Int32!`. These +properties would behave with the following characteristics, which mirror the +nil-resettable properties used elsewhere in Apple’s SDKs (for example, +`UIView.tintColor`): + +* Assigning a non-nil value to a property sets the field to that value. +* Assigning nil to a property clears the field (its internal representation is + nilled out). +* Reading the value of a property returns its value if it is set, or returns + its default value if it is not set. Reading a property never returns nil. + +The final point in the list above implies that the optional cannot be checked to +determine if the field is set to a value other than its default: it will never +be nil. Instead, we must provide `has*` methods for each field to allow the user +to check this. These methods will be public in proto2. In proto3, these methods +will be private (if generated at all), since the user can test the returned +value against the zero value for that type. + +### Autocreation of nested messages + +For convenience, dotting into an unset field representing a nested message will +return an instance of that message with default values. As in the Objective-C +implementation, this does not actually cause the field to be set until the +returned message is mutated. Fortunately, thanks to the way mutability of value +types is implemented in Swift, the language automatically handles the +reassignment-on-mutation for us. A static singleton instance containing default +values can be associated with each message that can be returned when reading, so +copies are only made by the Swift runtime when mutation occurs. For example, +given the following proto: + +```protobuf +message Node { + Node child = 1; + string value = 2 [default = "foo"]; +} +``` + +The following Swift code would act as commented, where setting deeply nested +properties causes the copies and mutations to occur as the assignment statement +is unwound: + +```swift +var node = Node() + +let s = node.child.child.value +// 1. node.child returns the "default Node". +// 2. Reading .child on the result of (1) returns the same default Node. +// 3. Reading .value on the result of (2) returns the default value "foo". + +node.child.child.value = "bar" +// 4. Setting .value on the default Node causes a copy to be made and sets +// the property on that copy. Subsequently, the language updates the +// value of "node.child.child" to point to that copy. +// 5. Updating "node.child.child" in (4) requires another copy, because +// "node.child" was also the instance of the default node. The copy is +// assigned back to "node.child". +// 6. Setting "node.child" in (5) is a simple value reassignment, since +// "node" is a mutable var. +``` + +In other words, the generated messages do not internally have to manage parental +relationships to backfill the appropriate properties on mutation. Swift provides +this for free. + +## Scalar value fields + +Proto scalar value fields will map to Swift types in the following way: + +.proto Type | Swift Type +----------- | ------------------- +`double` | `Double` +`float` | `Float` +`int32` | `Int32` +`int64` | `Int64` +`uint32` | `UInt32` +`uint64` | `UInt64` +`sint32` | `Int32` +`sint64` | `Int64` +`fixed32` | `UInt32` +`fixed64` | `UInt64` +`sfixed32` | `Int32` +`sfixed64` | `Int64` +`bool` | `Bool` +`string` | `String` +`bytes` | `Foundation.NSData` + +The proto spec defines a number of integral types that map to the same Swift +type; for example, `intXX`, `sintXX`, and `sfixedXX` are all signed integers, +and `uintXX` and `fixedXX` are both unsigned integers. No other language +implementation distinguishes these further, so we do not do so either. The +rationale is that the various types only serve to distinguish how the value is +**encoded on the wire**; once loaded in memory, the user is not concerned about +these variations. + +Swift’s lack of implicit conversions among types will make it slightly annoying +to use these types in a context expecting an `Int`, or vice-versa, but since +this is a data-interchange format with explicitly-sized fields, we should not +hide that information from the user. Users will have to explicitly write +`Int(message.myField)`, for example. + +## Embedded message fields + +Embedded message fields can be represented using an optional variable of the +generated message type. Thus, the message + +```protobuf +message Foo { + Bar bar = 1; +} +``` + +would be represented in Swift as + +```swift +public struct Foo: ProtoMessage { + public var bar: Bar! { + get { ... } + set { ... } + } +} +``` + +If the user explicitly sets `bar` to nil, or if it was never set when read from +the wire, retrieving the value of `bar` would return a default, statically +allocated instance of `Bar` containing default values for its fields. This +achieves the desired behavior for default values in the same way that scalar +fields are designed, and also allows users to deep-drill into complex object +graphs to get or set fields without checking for nil at each step. + +## Enum fields + +The design and implementation of enum fields will differ somewhat drastically +depending on whether the message being generated is a proto2 or proto3 message. + +### proto2 enums + +For proto2, we do not need to be concerned about unknown enum values, so we can +use the simple raw-value enum syntax provided by Swift. So the following enum in +proto2: + +```protobuf +enum ContentType { + TEXT = 0; + IMAGE = 1; +} +``` + +would become this Swift enum: + +```swift +public enum ContentType: Int32, NilLiteralConvertible { + case text = 0 + case image = 1 + + public init(nilLiteral: ()) { + self = .text + } +} +``` + +See below for the discussion about `NilLiteralConvertible`. + +### proto3 enums + +For proto3, we need to be able to preserve unknown enum values that may come +across the wire so that they can be written back if unmodified. We can +accomplish this in Swift by using a case with an associated value for unknowns. +So the following enum in proto3: + +```protobuf +enum ContentType { + TEXT = 0; + IMAGE = 1; +} +``` + +would become this Swift enum: + +```swift +public enum ContentType: RawRepresentable, NilLiteralConvertible { + case text + case image + case UNKNOWN_VALUE(Int32) + + public typealias RawValue = Int32 + + public init(nilLiteral: ()) { + self = .text + } + + public init(rawValue: RawValue) { + switch rawValue { + case 0: self = .text + case 1: self = .image + default: self = .UNKNOWN_VALUE(rawValue) + } + + public var rawValue: RawValue { + switch self { + case .text: return 0 + case .image: return 1 + case .UNKNOWN_VALUE(let value): return value + } + } +} +``` + +Note that the use of a parameterized case prevents us from inheriting from the +raw `Int32` type; Swift does not allow an enum with a raw type to have cases +with arguments. Instead, we must implement the raw value initializer and +computed property manually. The `UNKNOWN_VALUE` case is explicitly chosen to be +"ugly" so that it stands out and does not conflict with other possible case +names. + +Using this approach, proto3 consumers must always have a default case or handle +the `.UNKNOWN_VALUE` case to satisfy case exhaustion in a switch statement; the +Swift compiler considers it an error if switch statements are not exhaustive. + +### NilLiteralConvertible conformance + +This is required to clean up the usage of enum-typed properties in switch +statements. Unlike other field types, enum properties cannot be +implicitly-unwrapped optionals without requiring that uses in switch statements +be explicitly unwrapped. For example, if we consider a message with the enum +above, this usage will fail to compile: + +```swift +// Without NilLiteralConvertible conformance on ContentType +public struct SomeMessage: ProtoMessage { + public var contentType: ContentType! { ... } +} + +// ERROR: no case named text or image +switch someMessage.contentType { + case .text: { ... } + case .image: { ... } +} +``` + +Even though our implementation guarantees that `contentType` will never be nil, +if it is an optional type, its cases would be `some` and `none`, not the cases +of the underlying enum type. In order to use it in this context, the user must +write `someMessage.contentType!` in their switch statement. + +Making the enum itself `NilLiteralConvertible` permits us to make the property +non-optional, so the user can still set it to nil to clear it (i.e., reset it to +its default value), while eliminating the need to explicitly unwrap it in a +switch statement. + +```swift +// With NilLiteralConvertible conformance on ContentType +public struct SomeMessage: ProtoMessage { + // Note that the property type is no longer optional + public var contentType: ContentType { ... } +} + +// OK: Compiles and runs as expected +switch someMessage.contentType { + case .text: { ... } + case .image: { ... } +} + +// The enum can be reset to its default value this way +someMessage.contentType = nil +``` + +One minor oddity with this approach is that nil will be auto-converted to the +default value of the enum in any context, not just field assignment. In other +words, this is valid: + +```swift +func foo(contentType: ContentType) { ... } +foo(nil) // Inside foo, contentType == .text +``` + +That being said, the advantage of being able to simultaneously support +nil-resettability and switch-without-unwrapping outweighs this side effect, +especially if appropriately documented. It is our hope that a new form of +resettable properties will be added to Swift that eliminates this inconsistency. +Some community members have already drafted or sent proposals for review that +would benefit our designs: + +* [SE-0030: Property Behaviors] + (https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md) +* [Drafted: Resettable Properties] + (https://github.com/patters/swift-evolution/blob/master/proposals/0000-resettable-properties.md) + +### Enum aliases + +The `allow_alias` option in protobuf slightly complicates the use of Swift enums +to represent that type, because raw values of cases in an enum must be unique. +Swift lets us define static variables in an enum that alias actual cases. For +example, the following protobuf enum: + +```protobuf +enum Foo { + option allow_alias = true; + BAR = 0; + BAZ = 0; +} +``` + +will be represented in Swift as: + +```swift +public enum Foo: Int32, NilLiteralConvertible { + case bar = 0 + static public let baz = bar + + // ... etc. +} + +// Can still use .baz shorthand to reference the alias in contexts +// where the type is inferred +``` + +That is, we use the first name as the actual case and use static variables for +the other aliases. One drawback to this approach is that the static aliases +cannot be used as cases in a switch statement (the compiler emits the error +*“Enum case ‘baz’ not found in type ‘Foo’”*). However, in our own code bases, +there are only a few places where enum aliases are not mere renamings of an +older value, but they also don’t appear to be the type of value that one would +expect to switch on (for example, a group of named constants representing +metrics rather than a set of options), so this restriction is not significant. + +This strategy also implies that changing the name of an enum and adding the old +name as an alias below the new name will be a breaking change in the generated +Swift code. + +## Oneof types + +The `oneof` feature represents a “variant/union” data type that maps nicely to +Swift enums with associated values (algebraic types). These fields can also be +accessed independently though, and, specifically in the case of proto2, it’s +reasonable to expect access to default values when accessing a field that is not +explicitly set. + +Taking all this into account, we can represent a `oneof` in Swift with two sets +of constructs: + +* Properties in the message that correspond to the `oneof` fields. +* A nested enum named after the `oneof` and which provides the corresponding + field values as case arguments. + +This approach fulfills the needs of proto consumers by providing a +Swift-idiomatic way of simultaneously checking which field is set and accessing +its value, providing individual properties to access the default values +(important for proto2), and safely allows a field to be moved into a `oneof` +without breaking clients. + +Consider the following proto: + +```protobuf +message MyMessage { + oneof record { + string name = 1 [default = "unnamed"]; + int32 id_number = 2 [default = 0]; + } +} +``` + +In Swift, we would generate an enum, a property for that enum, and properties +for the fields themselves: + +```swift +public struct MyMessage: ProtoMessage { + public enum Record: NilLiteralConvertible { + case name(String) + case idNumber(Int32) + case NOT_SET + + public init(nilLiteral: ()) { self = .NOT_SET } + } + + // This is the "Swifty" way of accessing the value + public var record: Record { ... } + + // Direct access to the underlying fields + public var name: String! { ... } + public var idNumber: Int32! { ... } +} +``` + +This makes both usage patterns possible: + +```swift +// Usage 1: Case-based dispatch +switch message.record { + case .name(let name): + // Do something with name if it was explicitly set + case .idNumber(let id): + // Do something with id_number if it was explicitly set + case .NOT_SET: + // Do something if it’s not set +} + +// Usage 2: Direct access for default value fallback +// Sets the label text to the name if it was explicitly set, or to +// "unnamed" (the default value for the field) if id_number was set +// instead +let myLabel = UILabel() +myLabel.text = message.name +``` + +As with proto enums, the generated `oneof` enum conforms to +`NilLiteralConvertible` to avoid switch statement issues. Setting the property +to nil will clear it (i.e., reset it to `NOT_SET`). + +## Unknown Fields (proto2 only) + +To be written. + +## Extensions (proto2 only) + +To be written. + +## Reflection and Descriptors + +We will not include reflection or descriptors in the first version of the Swift +library. The use cases for reflection on mobile are not as strong and the static +data to represent the descriptors would add bloat when we wish to keep the code +size small. + +In the future, we will investigate whether they can be included as extensions +which might be able to be excluded from a build and/or automatically dead +stripped by the compiler if they are not used. + +## Appendix A: Rejected strategies to handle packages + +### Each package is its own Swift module + +Each proto package could be declared as its own Swift module, replacing dots +with underscores (e.g., package `foo.bar` becomes module `Foo_Bar`). Then, users +would simply import modules containing whatever proto modules they want to use +and refer to the generated types by their short names. + +**This solution is simply not possible, however.** Swift modules cannot +circularly reference each other, but there is no restriction against proto +packages doing so. Circular imports are forbidden (e.g., `foo.proto` importing +`bar.proto` importing `foo.proto`), but nothing prevents package `foo` from +using a type in package `bar` which uses a different type in package `foo`, as +long as there is no import cycle. If these packages were generated as Swift +modules, then `Foo` would contain an `import Bar` statement and `Bar` would +contain an `import Foo` statement, and there is no way to compile this. + +### Ad hoc namespacing with structs + +We can “fake” namespaces in Swift by declaring empty structs with private +initializers. Since modules are constructed based on compiler arguments, not by +syntactic constructs, and because there is no pure Swift way to define +submodules (even though Clang module maps support this), there is no +source-drive way to group generated code into namespaces aside from this +approach. + +Types can be added to those intermediate package structs using Swift extensions. +For example, a message `Baz` in package `foo.bar` could be represented in Swift +as follows: + +```swift +public struct Foo { + private init() {} +} + +public extension Foo { + public struct Bar { + private init() {} + } +} + +public extension Foo.Bar { + public struct Baz { + // Message fields and other methods + } +} + +let baz = Foo.Bar.Baz() +``` + +Each of these constructs would actually be defined in a separate file; Swift +lets us keep them separate and add multiple structs to a single “namespace” +through extensions. + +Unfortunately, these intermediate structs generate symbols of their own +(metatype information in the data segment). This becomes problematic if multiple +build targets contain Swift sources generated from different messages in the +same package. At link time, these symbols would collide, resulting in multiple +definition errors. + +This approach also has the disadvantage that there is no automatic “short” way +to refer to the generated messages at the deepest nesting levels; since this use +of structs is a hack around the lack of namespaces, there is no equivalent to +import (Java) or using (C++) to simplify this. Users would have to declare type +aliases to make this cleaner, or we would have to generate them for users. diff --git a/docs/third_party.md b/docs/third_party.md new file mode 100644 index 00000000..69ed6a38 --- /dev/null +++ b/docs/third_party.md @@ -0,0 +1,147 @@ +# Third-Party Add-ons for Protocol Buffers + +This page lists code related to Protocol Buffers which is developed and maintained by third parties. You may find this code useful, but note that **these projects are not affiliated with or endorsed by Google (unless explicitly marked)**; try them at your own risk. Also note that many projects here are in the early stages of development and not production-ready. + +If you have a project that should be listed here, please [send us a pull request](https://github.com/google/protobuf/pulls) to update this page. + +## Programming Languages + +These are projects we know about implementing Protocol Buffers for other programming languages: +* Action Script: http://code.google.com/p/protobuf-actionscript3/ +* Action Script: https://code.google.com/p/protoc-gen-as3/ +* Action Script: https://github.com/matrix3d/JProtoc +* C: https://github.com/protobuf-c/protobuf-c +* C: http://koti.kapsi.fi/jpa/nanopb/ +* C: https://github.com/cloudwu/pbc/ +* C: https://github.com/haberman/upb/wiki +* C: https://github.com/squidfunk/protobluff +* C++: https://github.com/google/protobuf (Google-official implementation) +* 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://www.prism.gatech.edu/~ndantam3/docs/s-protobuf/ +* Common Lisp: http://github.com/brown/protobuf +* 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 +* 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 +* Go: https://github.com/golang/protobuf (Google-official implementation) +* Go: http://code.google.com/p/goprotobuf/ +* Go: https://github.com/akunspy/gopbuf +* Haskell: http://hackage.haskell.org/package/hprotoc +* 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 ME: http://code.google.com/p/protobuf-javame/ +* Java ME: http://swingme.sourceforge.net/encode.shtml +* Java ME: http://github.com/ponderingpanda/protobuf-j2me +* Java ME: http://code.google.com/p/protobuf-j2me/ +* Javascript: http://code.google.com/p/protobuf-js/ +* Javascript: http://github.com/sirikata/protojs +* Javascript: https://github.com/dcodeIO/ProtoBuf.js +* Javascript: http://code.google.com/p/protobuf-for-node/ +* Javascript: http://code.google.com/p/protostuff/ +* Julia: https://github.com/tanmaykm/ProtoBuf.jl +* Lua: http://code.google.com/p/protoc-gen-lua/ +* Lua: http://github.com/indygreg/lua-protobuf +* Lua: https://github.com/Neopallium/lua-pb +* Matlab: http://code.google.com/p/protobuf-matlab/ +* Mercury: http://code.google.com/p/protobuf-mercury/ +* Objective C: http://code.google.com/p/protobuf-objc/ +* Objective C: https://github.com/alexeyxo/protobuf-objc +* OCaml: http://piqi.org/ +* Perl: http://groups.google.com/group/protobuf-perl +* Perl: http://search.cpan.org/perldoc?Google::ProtocolBuffers +* Perl/XS: http://code.google.com/p/protobuf-perlxs/ +* PHP: http://code.google.com/p/pb4php/ +* PHP: https://github.com/allegro/php-protobuf/ +* PHP: https://github.com/chobie/php-protocolbuffers +* PHP: http://drslump.github.com/Protobuf-PHP +* Prolog: http://www.swi-prolog.org/pldoc/package/protobufs.html +* Python: https://github.com/google/protobuf (Google-official implementation) +* Python: http://eigenein.github.com/protobuf/ +* R: http://cran.r-project.org/package=RProtoBuf +* Ruby: http://code.google.com/p/ruby-protobuf/ +* Ruby: http://github.com/mozy/ruby-protocol-buffers +* Ruby: https://github.com/bmizerany/beefcake/tree/master/lib/beefcake +* Ruby: https://github.com/localshred/protobuf +* Rust: https://github.com/stepancheg/rust-protobuf/ +* 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/ +* Swift: https://github.com/alexeyxo/protobuf-swift +* Vala: https://launchpad.net/protobuf-vala +* Visual Basic: http://code.google.com/p/protobuf-net/ + +## RPC Implementations + +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://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://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/ebencheung/arab (C++) +* http://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++) + +## Other Utilities + +There are miscellaneous other things you may find useful as a Protocol Buffers developer. + +* [NetBeans IDE plugin](http://code.google.com/p/protobuf-netbeans-plugin/) +* [Wireshark/Ethereal packet sniffer plugin](http://code.google.com/p/protobuf-wireshark/) +* [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) +* [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/) +* [C++ Builder compatible protobuf](https://github.com/saadware/protobuf-cppbuilder) +* Maven Protocol Compiler Plugin + * https://github.com/sergei-ivanov/maven-protoc-plugin/ + * http://igor-petruk.github.com/protobuf-maven-plugin/ + * http://code.google.com/p/maven-protoc-plugin/ + * https://github.com/os72/protoc-jar-maven-plugin +* [Documentation generator plugin (Markdown/HTML/DocBook/...)](https://github.com/estan/protoc-gen-doc) +* [DocBook generator for .proto files](http://code.google.com/p/protoc-gen-docbook/) +* [Protobuf for nginx module](https://github.com/dbcode/protobuf-nginx/) +* [RSpec matchers and Cucumber step defs for testing Protocol Buffers](https://github.com/connamara/protobuf_spec) +* [Sbt plugin for Protocol Buffers](https://github.com/Atry/sbt-cppp) +* [Gradle Protobuf Plugin](https://github.com/aantono/gradle-plugin-protobuf) +* [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) +* [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) 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 9f418f2b..03c0d579 100644 --- a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java +++ b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java @@ -50,17 +50,23 @@ import java.util.Map; * * @author kenton@google.com Kenton Varda */ -public abstract class AbstractMessage extends AbstractMessageLite - implements Message { +public abstract class AbstractMessage + // TODO(dweis): Update GeneratedMessage to parameterize with MessageType and BuilderType. + extends AbstractMessageLite + implements Message { + + @Override public boolean isInitialized() { return MessageReflection.isInitialized(this); } + @Override public List<String> findInitializationErrors() { return MessageReflection.findMissingFields(this); } + @Override public String getInitializationErrorString() { return MessageReflection.delimitWithCommas(findInitializationErrors()); } @@ -83,12 +89,14 @@ public abstract class AbstractMessage extends AbstractMessageLite return TextFormat.printToString(this); } + @Override public void writeTo(final CodedOutputStream output) throws IOException { MessageReflection.writeMessageTo(this, getAllFields(), output, false); } protected int memoizedSize = -1; + @Override public int getSerializedSize() { int size = memoizedSize; if (size != -1) { @@ -288,8 +296,8 @@ public abstract class AbstractMessage extends AbstractMessageLite * other methods. */ @SuppressWarnings("unchecked") - public static abstract class Builder<BuilderType extends Builder> - extends AbstractMessageLite.Builder<BuilderType> + public static abstract class Builder<BuilderType extends Builder<BuilderType>> + extends AbstractMessageLite.Builder implements Message.Builder { // The compiler produces an error if this is not declared explicitly. @Override @@ -314,6 +322,7 @@ public abstract class AbstractMessage extends AbstractMessageLite throw new UnsupportedOperationException("clearOneof() is not implemented."); } + @Override public BuilderType clear() { for (final Map.Entry<FieldDescriptor, Object> entry : getAllFields().entrySet()) { @@ -322,14 +331,22 @@ public abstract class AbstractMessage extends AbstractMessageLite return (BuilderType) this; } + @Override public List<String> findInitializationErrors() { return MessageReflection.findMissingFields(this); } + @Override public String getInitializationErrorString() { return MessageReflection.delimitWithCommas(findInitializationErrors()); } + + @Override + protected BuilderType internalMergeFrom(AbstractMessageLite other) { + return mergeFrom((Message) other); + } + @Override public BuilderType mergeFrom(final Message other) { if (other.getDescriptorForType() != getDescriptorForType()) { throw new IllegalArgumentException( @@ -407,6 +424,7 @@ public abstract class AbstractMessage extends AbstractMessageLite return (BuilderType) this; } + @Override public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) { setUnknownFields( UnknownFieldSet.newBuilder(getUnknownFields()) @@ -415,17 +433,19 @@ public abstract class AbstractMessage extends AbstractMessageLite return (BuilderType) this; } + @Override public Message.Builder getFieldBuilder(final FieldDescriptor field) { throw new UnsupportedOperationException( "getFieldBuilder() called on an unsupported message type."); } - public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, - int index) { + @Override + public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) { throw new UnsupportedOperationException( "getRepeatedFieldBuilder() called on an unsupported message type."); } + @Override public String toString() { return TextFormat.printToString(this); } @@ -462,7 +482,7 @@ public abstract class AbstractMessage extends AbstractMessageLite @Override public BuilderType mergeFrom(final ByteString data) throws InvalidProtocolBufferException { - return super.mergeFrom(data); + return (BuilderType) super.mergeFrom(data); } @Override @@ -470,20 +490,20 @@ public abstract class AbstractMessage extends AbstractMessageLite final ByteString data, final ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { - return super.mergeFrom(data, extensionRegistry); + return (BuilderType) super.mergeFrom(data, extensionRegistry); } @Override public BuilderType mergeFrom(final byte[] data) throws InvalidProtocolBufferException { - return super.mergeFrom(data); + return (BuilderType) super.mergeFrom(data); } @Override public BuilderType mergeFrom( final byte[] data, final int off, final int len) throws InvalidProtocolBufferException { - return super.mergeFrom(data, off, len); + return (BuilderType) super.mergeFrom(data, off, len); } @Override @@ -491,7 +511,7 @@ public abstract class AbstractMessage extends AbstractMessageLite final byte[] data, final ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { - return super.mergeFrom(data, extensionRegistry); + return (BuilderType) super.mergeFrom(data, extensionRegistry); } @Override @@ -499,13 +519,13 @@ public abstract class AbstractMessage extends AbstractMessageLite final byte[] data, final int off, final int len, final ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { - return super.mergeFrom(data, off, len, extensionRegistry); + return (BuilderType) super.mergeFrom(data, off, len, extensionRegistry); } @Override public BuilderType mergeFrom(final InputStream input) throws IOException { - return super.mergeFrom(input); + return (BuilderType) super.mergeFrom(input); } @Override @@ -513,7 +533,7 @@ public abstract class AbstractMessage extends AbstractMessageLite final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException { - return super.mergeFrom(input, extensionRegistry); + return (BuilderType) super.mergeFrom(input, extensionRegistry); } @Override diff --git a/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java b/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java index 12384983..43736dd1 100644 --- a/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java +++ b/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java @@ -43,9 +43,13 @@ import java.util.Collection; * * @author kenton@google.com Kenton Varda */ -public abstract class AbstractMessageLite implements MessageLite { +public abstract class AbstractMessageLite< + MessageType extends AbstractMessageLite<MessageType, BuilderType>, + BuilderType extends AbstractMessageLite.Builder<MessageType, BuilderType>> + implements MessageLite { protected int memoizedHashCode = 0; - + + @Override public ByteString toByteString() { try { final ByteString.CodedBuilder out = @@ -59,6 +63,7 @@ public abstract class AbstractMessageLite implements MessageLite { } } + @Override public byte[] toByteArray() { try { final byte[] result = new byte[getSerializedSize()]; @@ -73,6 +78,7 @@ public abstract class AbstractMessageLite implements MessageLite { } } + @Override public void writeTo(final OutputStream output) throws IOException { final int bufferSize = CodedOutputStream.computePreferredBufferSize(getSerializedSize()); @@ -82,6 +88,7 @@ public abstract class AbstractMessageLite implements MessageLite { codedOutput.flush(); } + @Override public void writeDelimitedTo(final OutputStream output) throws IOException { final int serialized = getSerializedSize(); final int bufferSize = CodedOutputStream.computePreferredBufferSize( @@ -120,25 +127,27 @@ public abstract class AbstractMessageLite implements MessageLite { * other methods. */ @SuppressWarnings("unchecked") - public static abstract class Builder<BuilderType extends Builder> + public abstract static class Builder< + MessageType extends AbstractMessageLite<MessageType, BuilderType>, + BuilderType extends Builder<MessageType, BuilderType>> implements MessageLite.Builder { // The compiler produces an error if this is not declared explicitly. @Override public abstract BuilderType clone(); - public BuilderType mergeFrom(final CodedInputStream input) - throws IOException { + @Override + public BuilderType mergeFrom(final CodedInputStream input) throws IOException { return mergeFrom(input, ExtensionRegistryLite.getEmptyRegistry()); } // Re-defined here for return type covariance. + @Override public abstract BuilderType mergeFrom( - final CodedInputStream input, - final ExtensionRegistryLite extensionRegistry) + final CodedInputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException; - public BuilderType mergeFrom(final ByteString data) - throws InvalidProtocolBufferException { + @Override + public BuilderType mergeFrom(final ByteString data) throws InvalidProtocolBufferException { try { final CodedInputStream input = data.newCodedInput(); mergeFrom(input); @@ -153,9 +162,9 @@ public abstract class AbstractMessageLite implements MessageLite { } } + @Override public BuilderType mergeFrom( - final ByteString data, - final ExtensionRegistryLite extensionRegistry) + final ByteString data, final ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { try { final CodedInputStream input = data.newCodedInput(); @@ -171,14 +180,14 @@ public abstract class AbstractMessageLite implements MessageLite { } } - public BuilderType mergeFrom(final byte[] data) - throws InvalidProtocolBufferException { + @Override + public BuilderType mergeFrom(final byte[] data) throws InvalidProtocolBufferException { return mergeFrom(data, 0, data.length); } - public BuilderType mergeFrom(final byte[] data, final int off, - final int len) - throws InvalidProtocolBufferException { + @Override + public BuilderType mergeFrom(final byte[] data, final int off, final int len) + throws InvalidProtocolBufferException { try { final CodedInputStream input = CodedInputStream.newInstance(data, off, len); @@ -194,15 +203,17 @@ public abstract class AbstractMessageLite implements MessageLite { } } - public BuilderType mergeFrom( - final byte[] data, - final ExtensionRegistryLite extensionRegistry) + @Override + public BuilderType mergeFrom(final byte[] data, final ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { return mergeFrom(data, 0, data.length, 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 { try { @@ -220,6 +231,7 @@ public abstract class AbstractMessageLite implements MessageLite { } } + @Override public BuilderType mergeFrom(final InputStream input) throws IOException { final CodedInputStream codedInput = CodedInputStream.newInstance(input); mergeFrom(codedInput); @@ -227,10 +239,9 @@ public abstract class AbstractMessageLite implements MessageLite { return (BuilderType) this; } + @Override public BuilderType mergeFrom( - final InputStream input, - final ExtensionRegistryLite extensionRegistry) - throws IOException { + final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException { final CodedInputStream codedInput = CodedInputStream.newInstance(input); mergeFrom(codedInput, extensionRegistry); codedInput.checkLastTagWas(0); @@ -292,10 +303,9 @@ public abstract class AbstractMessageLite implements MessageLite { } } + @Override public boolean mergeDelimitedFrom( - final InputStream input, - final ExtensionRegistryLite extensionRegistry) - throws IOException { + final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException { final int firstByte = input.read(); if (firstByte == -1) { return false; @@ -306,11 +316,24 @@ public abstract class AbstractMessageLite implements MessageLite { return true; } - public boolean mergeDelimitedFrom(final InputStream input) - throws IOException { + @Override + public boolean mergeDelimitedFrom(final InputStream input) throws IOException { return mergeDelimitedFrom(input, ExtensionRegistryLite.getEmptyRegistry()); } + + @Override + @SuppressWarnings("unchecked") // isInstance takes care of this + public BuilderType mergeFrom(final MessageLite other) { + if (!getDefaultInstanceForType().getClass().isInstance(other)) { + throw new IllegalArgumentException( + "mergeFrom(MessageLite) can only merge messages of the same type."); + } + + return internalMergeFrom((MessageType) other); + } + + protected abstract BuilderType internalMergeFrom(MessageType message); /** * Construct an UninitializedMessageException reporting missing fields in 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 1a4c6311..66b0ee3b 100644 --- a/java/core/src/main/java/com/google/protobuf/AbstractParser.java +++ b/java/core/src/main/java/com/google/protobuf/AbstractParser.java @@ -78,26 +78,27 @@ public abstract class AbstractParser<MessageType extends MessageLite> private static final ExtensionRegistryLite EMPTY_REGISTRY = ExtensionRegistryLite.getEmptyRegistry(); + @Override public MessageType parsePartialFrom(CodedInputStream input) throws InvalidProtocolBufferException { return parsePartialFrom(input, EMPTY_REGISTRY); } - public MessageType parseFrom(CodedInputStream input, - ExtensionRegistryLite extensionRegistry) + @Override + public MessageType parseFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { return checkMessageInitialized( parsePartialFrom(input, extensionRegistry)); } - public MessageType parseFrom(CodedInputStream input) - throws InvalidProtocolBufferException { + @Override + public MessageType parseFrom(CodedInputStream input) throws InvalidProtocolBufferException { return parseFrom(input, EMPTY_REGISTRY); } - public MessageType parsePartialFrom(ByteString data, - ExtensionRegistryLite extensionRegistry) - throws InvalidProtocolBufferException { + @Override + public MessageType parsePartialFrom(ByteString data, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { MessageType message; try { CodedInputStream input = data.newCodedInput(); @@ -113,24 +114,25 @@ public abstract class AbstractParser<MessageType extends MessageLite> } } - public MessageType parsePartialFrom(ByteString data) - throws InvalidProtocolBufferException { + @Override + public MessageType parsePartialFrom(ByteString data) throws InvalidProtocolBufferException { return parsePartialFrom(data, EMPTY_REGISTRY); } - public MessageType parseFrom(ByteString data, - ExtensionRegistryLite extensionRegistry) + @Override + public MessageType parseFrom(ByteString data, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { return checkMessageInitialized(parsePartialFrom(data, extensionRegistry)); } - public MessageType parseFrom(ByteString data) - throws InvalidProtocolBufferException { + @Override + public MessageType parseFrom(ByteString data) throws InvalidProtocolBufferException { return parseFrom(data, EMPTY_REGISTRY); } - public MessageType parsePartialFrom(byte[] data, int off, int len, - ExtensionRegistryLite extensionRegistry) + @Override + public MessageType parsePartialFrom( + byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { try { CodedInputStream input = CodedInputStream.newInstance(data, off, len); @@ -146,47 +148,50 @@ public abstract class AbstractParser<MessageType extends MessageLite> } } + @Override public MessageType parsePartialFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException { return parsePartialFrom(data, off, len, EMPTY_REGISTRY); } - public MessageType parsePartialFrom(byte[] data, - ExtensionRegistryLite extensionRegistry) + @Override + public MessageType parsePartialFrom(byte[] data, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { return parsePartialFrom(data, 0, data.length, extensionRegistry); } - public MessageType parsePartialFrom(byte[] data) - throws InvalidProtocolBufferException { + @Override + public MessageType parsePartialFrom(byte[] data) throws InvalidProtocolBufferException { return parsePartialFrom(data, 0, data.length, EMPTY_REGISTRY); } - public MessageType parseFrom(byte[] data, int off, int len, - ExtensionRegistryLite extensionRegistry) + @Override + public MessageType parseFrom( + byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { return checkMessageInitialized( parsePartialFrom(data, off, len, extensionRegistry)); } + @Override public MessageType parseFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException { return parseFrom(data, off, len, EMPTY_REGISTRY); } - public MessageType parseFrom(byte[] data, - ExtensionRegistryLite extensionRegistry) + @Override + public MessageType parseFrom(byte[] data, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { return parseFrom(data, 0, data.length, extensionRegistry); } - public MessageType parseFrom(byte[] data) - throws InvalidProtocolBufferException { + @Override + public MessageType parseFrom(byte[] data) throws InvalidProtocolBufferException { return parseFrom(data, EMPTY_REGISTRY); } - public MessageType parsePartialFrom(InputStream input, - ExtensionRegistryLite extensionRegistry) + @Override + public MessageType parsePartialFrom(InputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { CodedInputStream codedInput = CodedInputStream.newInstance(input); MessageType message = parsePartialFrom(codedInput, extensionRegistry); @@ -198,26 +203,26 @@ public abstract class AbstractParser<MessageType extends MessageLite> return message; } - public MessageType parsePartialFrom(InputStream input) - throws InvalidProtocolBufferException { + @Override + public MessageType parsePartialFrom(InputStream input) throws InvalidProtocolBufferException { return parsePartialFrom(input, EMPTY_REGISTRY); } - public MessageType parseFrom(InputStream input, - ExtensionRegistryLite extensionRegistry) + @Override + public MessageType parseFrom(InputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { return checkMessageInitialized( parsePartialFrom(input, extensionRegistry)); } - public MessageType parseFrom(InputStream input) - throws InvalidProtocolBufferException { + @Override + public MessageType parseFrom(InputStream input) throws InvalidProtocolBufferException { return parseFrom(input, EMPTY_REGISTRY); } + @Override public MessageType parsePartialDelimitedFrom( - InputStream input, - ExtensionRegistryLite extensionRegistry) + InputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { int size; try { @@ -233,21 +238,21 @@ public abstract class AbstractParser<MessageType extends MessageLite> return parsePartialFrom(limitedInput, extensionRegistry); } + @Override public MessageType parsePartialDelimitedFrom(InputStream input) throws InvalidProtocolBufferException { return parsePartialDelimitedFrom(input, EMPTY_REGISTRY); } - public MessageType parseDelimitedFrom( - InputStream input, - ExtensionRegistryLite extensionRegistry) + @Override + public MessageType parseDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { return checkMessageInitialized( parsePartialDelimitedFrom(input, extensionRegistry)); } - public MessageType parseDelimitedFrom(InputStream input) - throws InvalidProtocolBufferException { + @Override + public MessageType parseDelimitedFrom(InputStream input) throws InvalidProtocolBufferException { return parseDelimitedFrom(input, EMPTY_REGISTRY); } } 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 bb6446b2..b17db6e0 100644 --- a/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java +++ b/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java @@ -34,19 +34,25 @@ import com.google.protobuf.Internal.ProtobufList; import java.util.AbstractList; import java.util.Collection; +import java.util.List; +import java.util.RandomAccess; /** * An abstract implementation of {@link ProtobufList} which manages mutability semantics. All mutate - * methods are check if the list is mutable before proceeding. Subclasses must invoke + * methods must check if the list is mutable before proceeding. Subclasses must invoke * {@link #ensureIsMutable()} manually when overriding those methods. + * <p> + * This implementation assumes all subclasses are array based, supporting random access. */ abstract class AbstractProtobufList<E> extends AbstractList<E> implements ProtobufList<E> { + protected static final int DEFAULT_CAPACITY = 10; + /** * Whether or not this list is modifiable. */ private boolean isMutable; - + /** * Constructs a mutable list by default. */ @@ -55,6 +61,44 @@ abstract class AbstractProtobufList<E> extends AbstractList<E> implements Protob } @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof List)) { + return false; + } + // Handle lists that do not support RandomAccess as efficiently as possible by using an iterator + // based approach in our super class. Otherwise our index based approach will avoid those + // allocations. + if (!(o instanceof RandomAccess)) { + return super.equals(o); + } + + List<?> other = (List<?>) o; + final int size = size(); + if (size != other.size()) { + return false; + } + for (int i = 0; i < size; i++) { + if (!get(i).equals(other.get(i))) { + return false; + } + } + return true; + } + + @Override + public int hashCode() { + final int size = size(); + int hashCode = 1; + for (int i = 0; i < size; i++) { + hashCode = (31 * hashCode) + get(i).hashCode(); + } + return hashCode; + } + + @Override public boolean add(E e) { ensureIsMutable(); return super.add(e); 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 70e042f5..8b2820b6 100644 --- a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java @@ -34,7 +34,6 @@ import com.google.protobuf.Internal.BooleanList; import java.util.Arrays; import java.util.Collection; -import java.util.List; import java.util.RandomAccess; /** @@ -45,8 +44,6 @@ import java.util.RandomAccess; final class BooleanArrayList extends AbstractProtobufList<Boolean> implements BooleanList, RandomAccess { - private static final int DEFAULT_CAPACITY = 10; - private static final BooleanArrayList EMPTY_LIST = new BooleanArrayList(); static { EMPTY_LIST.makeImmutable(); @@ -60,7 +57,7 @@ final class BooleanArrayList * The backing store for the list. */ private boolean[] array; - + /** * The size of the list distinct from the length of the array. That is, it is the number of * elements set in the list. @@ -71,35 +68,57 @@ final class BooleanArrayList * Constructs a new mutable {@code BooleanArrayList} with default capacity. */ BooleanArrayList() { - this(DEFAULT_CAPACITY); + this(new boolean[DEFAULT_CAPACITY], 0); } /** - * Constructs a new mutable {@code BooleanArrayList} with the provided capacity. + * Constructs a new mutable {@code BooleanArrayList}. */ - BooleanArrayList(int capacity) { - array = new boolean[capacity]; - size = 0; + private BooleanArrayList(boolean[] array, int size) { + this.array = array; + this.size = size; } - - /** - * Constructs a new mutable {@code BooleanArrayList} containing the same elements as - * {@code other}. - */ - BooleanArrayList(List<Boolean> other) { - if (other instanceof BooleanArrayList) { - BooleanArrayList list = (BooleanArrayList) other; - array = list.array.clone(); - size = list.size; - } else { - size = other.size(); - array = new boolean[size]; - for (int i = 0; i < size; i++) { - array[i] = other.get(i); + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof BooleanArrayList)) { + return super.equals(o); + } + BooleanArrayList other = (BooleanArrayList) o; + if (size != other.size) { + return false; + } + + final boolean[] arr = other.array; + for (int i = 0; i < size; i++) { + if (array[i] != arr[i]) { + return false; } } + + return true; } - + + @Override + public int hashCode() { + int result = 1; + for (int i = 0; i < size; i++) { + result = (31 * result) + Internal.hashBoolean(array[i]); + } + return result; + } + + @Override + public BooleanList mutableCopyWithCapacity(int capacity) { + if (capacity < size) { + throw new IllegalArgumentException(); + } + return new BooleanArrayList(Arrays.copyOf(array, capacity), size); + } + @Override public Boolean get(int index) { return getBoolean(index); 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 b92394b8..ad174d0f 100644 --- a/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java +++ b/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java @@ -30,11 +30,18 @@ package com.google.protobuf; +import static java.lang.Math.max; + import com.google.protobuf.Utf8.UnpairedSurrogateException; import java.io.IOException; import java.io.OutputStream; +import java.lang.reflect.Field; +import java.nio.BufferOverflowException; import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.security.AccessController; +import java.security.PrivilegedExceptionAction; import java.util.logging.Level; import java.util.logging.Logger; @@ -50,23 +57,21 @@ import java.util.logging.Logger; * * <p>This class is totally unsynchronized. */ -public final class CodedOutputStream { +public abstract class CodedOutputStream extends ByteOutput { private static final Logger logger = Logger.getLogger(CodedOutputStream.class.getName()); + private static final sun.misc.Unsafe UNSAFE = getUnsafe(); + private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = supportsUnsafeArrayOperations(); + private static final long ARRAY_BASE_OFFSET = byteArrayBaseOffset(); - private static final int LITTLE_ENDIAN_64_SIZE = 8; + private static final int FIXED_32_SIZE = 4; + private static final int FIXED_64_SIZE = 8; + private static final int MAX_VARINT_SIZE = 10; /** * @deprecated Use {@link #computeFixed32SizeNoTag(int)} instead. */ - @Deprecated public static final int LITTLE_ENDIAN_32_SIZE = 4; - - // TODO(dweis): Consider migrating to a ByteBuffer. - private final byte[] buffer; - private final int limit; - private int position; - private int totalBytesWritten = 0; - - private final OutputStream output; + @Deprecated + public static final int LITTLE_ENDIAN_32_SIZE = FIXED_32_SIZE; /** * The buffer size used in {@link #newInstance(OutputStream)}. @@ -87,34 +92,27 @@ public final class CodedOutputStream { return dataLength; } - private CodedOutputStream(final byte[] buffer, final int offset, final int length) { - output = null; - this.buffer = buffer; - position = offset; - limit = offset + length; - } - - private CodedOutputStream(final OutputStream output, final byte[] buffer) { - this.output = output; - this.buffer = buffer; - position = 0; - limit = buffer.length; - } - /** - * Create a new {@code CodedOutputStream} wrapping the given - * {@code OutputStream}. + * Create a new {@code CodedOutputStream} wrapping the given {@code OutputStream}. + * + * <p> NOTE: The provided {@link OutputStream} <strong>MUST NOT</strong> 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); } /** - * Create a new {@code CodedOutputStream} wrapping the given - * {@code OutputStream} with a given buffer size. + * Create a new {@code CodedOutputStream} wrapping the given {@code OutputStream} with a given + * buffer size. + * + * <p> NOTE: The provided {@link OutputStream} <strong>MUST NOT</strong> 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 CodedOutputStream(output, new byte[bufferSize]); + return new OutputStreamEncoder(output, bufferSize); } /** @@ -137,160 +135,144 @@ public final class CodedOutputStream { */ public static CodedOutputStream newInstance( final byte[] flatArray, final int offset, final int length) { - return new CodedOutputStream(flatArray, offset, length); + return new ArrayEncoder(flatArray, offset, length); } /** - * Create a new {@code CodedOutputStream} that writes to the given ByteBuffer. + * Create a new {@code CodedOutputStream} that writes to the given {@link ByteBuffer}. */ public static CodedOutputStream newInstance(ByteBuffer byteBuffer) { - return newInstance(byteBuffer, DEFAULT_BUFFER_SIZE); + if (byteBuffer.hasArray()) { + return new NioHeapEncoder(byteBuffer); + } + return new NioEncoder(byteBuffer); } /** - * Create a new {@code CodedOutputStream} that writes to the given ByteBuffer. + * 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. */ - public static CodedOutputStream newInstance(ByteBuffer byteBuffer, int bufferSize) { - return newInstance(new ByteBufferOutputStream(byteBuffer), bufferSize); + @Deprecated + public static CodedOutputStream newInstance(ByteBuffer byteBuffer, + @SuppressWarnings("unused") int unused) { + return newInstance(byteBuffer); } - private static class ByteBufferOutputStream extends OutputStream { - private final ByteBuffer byteBuffer; - - public ByteBufferOutputStream(ByteBuffer byteBuffer) { - this.byteBuffer = byteBuffer; + /** + * Create a new {@code CodedOutputStream} that writes to the provided {@link ByteOutput}. + * + * <p> NOTE: The {@link ByteOutput} <strong>MUST NOT</strong> 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. + */ + static CodedOutputStream newInstance(ByteOutput byteOutput, int bufferSize) { + if (bufferSize < 0) { + throw new IllegalArgumentException("bufferSize must be positive"); } - @Override - public void write(int b) throws IOException { - byteBuffer.put((byte) b); - } + return new ByteOutputEncoder(byteOutput, bufferSize); + } - @Override - public void write(byte[] data, int offset, int length) throws IOException { - byteBuffer.put(data, offset, length); - } + // Disallow construction outside of this class. + private CodedOutputStream() { } // ----------------------------------------------------------------- /** Encode and write a tag. */ - public void writeTag(final int fieldNumber, final int wireType) throws IOException { - writeRawVarint32(WireFormat.makeTag(fieldNumber, wireType)); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeTag(int fieldNumber, int wireType) throws IOException; /** Write an {@code int32} field, including tag, to the stream. */ - public void writeInt32(final int fieldNumber, final int value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); - writeInt32NoTag(value); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeInt32(int fieldNumber, int value) throws IOException; /** Write a {@code uint32} field, including tag, to the stream. */ - public void writeUInt32(final int fieldNumber, final int value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); - writeUInt32NoTag(value); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeUInt32(int fieldNumber, int value) throws IOException; /** Write a {@code sint32} field, including tag, to the stream. */ - public void writeSInt32(final int fieldNumber, final int value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); - writeSInt32NoTag(value); + public final void writeSInt32(final int fieldNumber, final int value) throws IOException { + writeUInt32(fieldNumber, encodeZigZag32(value)); } /** Write a {@code fixed32} field, including tag, to the stream. */ - public void writeFixed32(final int fieldNumber, final int value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); - writeFixed32NoTag(value); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeFixed32(int fieldNumber, int value) throws IOException; /** Write an {@code sfixed32} field, including tag, to the stream. */ - public void writeSFixed32(final int fieldNumber, final int value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); - writeSFixed32NoTag(value); + public final void writeSFixed32(final int fieldNumber, final int value) throws IOException { + writeFixed32(fieldNumber, value); } /** Write an {@code int64} field, including tag, to the stream. */ - public void writeInt64(final int fieldNumber, final long value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); - writeInt64NoTag(value); + public final void writeInt64(final int fieldNumber, final long value) throws IOException { + writeUInt64(fieldNumber, value); } /** Write a {@code uint64} field, including tag, to the stream. */ - public void writeUInt64(final int fieldNumber, final long value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); - writeUInt64NoTag(value); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeUInt64(int fieldNumber, long value) throws IOException; /** Write an {@code sint64} field, including tag, to the stream. */ - public void writeSInt64(final int fieldNumber, final long value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); - writeSInt64NoTag(value); + public final void writeSInt64(final int fieldNumber, final long value) throws IOException { + writeUInt64(fieldNumber, encodeZigZag64(value)); } /** Write a {@code fixed64} field, including tag, to the stream. */ - public void writeFixed64(final int fieldNumber, final long value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); - writeFixed64NoTag(value); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeFixed64(int fieldNumber, long value) throws IOException; /** Write an {@code sfixed64} field, including tag, to the stream. */ - public void writeSFixed64(final int fieldNumber, final long value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); - writeSFixed64NoTag(value); + public final void writeSFixed64(final int fieldNumber, final long value) throws IOException { + writeFixed64(fieldNumber, value); } /** Write a {@code float} field, including tag, to the stream. */ - public void writeFloat(final int fieldNumber, final float value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); - writeFloatNoTag(value); + public final void writeFloat(final int fieldNumber, final float value) throws IOException { + writeFixed32(fieldNumber, Float.floatToRawIntBits(value)); } /** Write a {@code double} field, including tag, to the stream. */ - public void writeDouble(final int fieldNumber, final double value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); - writeDoubleNoTag(value); + public final void writeDouble(final int fieldNumber, final double value) throws IOException { + writeFixed64(fieldNumber, Double.doubleToRawLongBits(value)); } /** Write a {@code bool} field, including tag, to the stream. */ - public void writeBool(final int fieldNumber, final boolean value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); - writeBoolNoTag(value); - } + // Abstract to avoid overhead of additional virtual method calls. + 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). */ - public void writeEnum(final int fieldNumber, final int value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); - writeEnumNoTag(value); + public final void writeEnum(final int fieldNumber, final int value) throws IOException { + writeInt32(fieldNumber, value); } /** Write a {@code string} field, including tag, to the stream. */ - public void writeString(final int fieldNumber, final String value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); - writeStringNoTag(value); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeString(int fieldNumber, String value) throws IOException; /** Write a {@code bytes} field, including tag, to the stream. */ - public void writeBytes(final int fieldNumber, final ByteString value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); - writeBytesNoTag(value); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeBytes(int fieldNumber, ByteString value) throws IOException; /** Write a {@code bytes} field, including tag, to the stream. */ - public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); - writeByteArrayNoTag(value); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeByteArray(int fieldNumber, byte[] value) throws IOException; /** Write a {@code bytes} field, including tag, to the stream. */ - public void writeByteArray( - final int fieldNumber, final byte[] value, final int offset, final int length) - throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); - writeByteArrayNoTag(value, offset, length); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeByteArray(int fieldNumber, byte[] value, int offset, int length) + throws IOException; /** * Write a {@code bytes} field, including tag, to the stream. @@ -302,67 +284,36 @@ public final class CodedOutputStream { * of a ByteBuffer, you can call * {@code writeByteBuffer(fieldNumber, byteBuffer.slice())}. */ - public void writeByteBuffer(final int fieldNumber, final ByteBuffer value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); - writeByteBufferNoTag(value); - } - - /** Write a single byte. */ - public void writeRawByte(final byte value) throws IOException { - if (position == limit) { - refreshBuffer(); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeByteBuffer(int fieldNumber, ByteBuffer value) throws IOException; - buffer[position++] = value; - ++totalBytesWritten; + /** + * Write a single byte. + */ + public final void writeRawByte(final byte value) throws IOException { + write(value); } /** Write a single byte, represented by an integer value. */ - public void writeRawByte(final int value) throws IOException { - writeRawByte((byte) value); + public final void writeRawByte(final int value) throws IOException { + write((byte) value); } /** Write an array of bytes. */ - public void writeRawBytes(final byte[] value) throws IOException { - writeRawBytes(value, 0, value.length); + public final void writeRawBytes(final byte[] value) throws IOException { + write(value, 0, value.length); } - /** Write part of an array of bytes. */ - public void writeRawBytes(final 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); - position += length; - totalBytesWritten += length; - } else { - // Write extends past current buffer. Fill the rest of this buffer and - // flush. - final int bytesWritten = limit - position; - System.arraycopy(value, offset, buffer, position, bytesWritten); - offset += bytesWritten; - length -= bytesWritten; - position = limit; - totalBytesWritten += bytesWritten; - 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. - System.arraycopy(value, offset, buffer, 0, length); - position = length; - } else { - // Write is very big. Let's do it all at once. - output.write(value, offset, length); - } - totalBytesWritten += length; - } + /** + * Write part of an array of bytes. + */ + public final void writeRawBytes(final byte[] value, int offset, int length) throws IOException { + write(value, offset, length); } /** Write a byte string. */ - public void writeRawBytes(final ByteString value) throws IOException { - writeRawBytes(value, 0, value.size()); + public final void writeRawBytes(final ByteString value) throws IOException { + value.writeTo(this); } /** @@ -374,155 +325,138 @@ public final class CodedOutputStream { * write the remaining bytes of a ByteBuffer, you can call * {@code writeRawBytes(byteBuffer.slice())}. */ - public void writeRawBytes(final ByteBuffer value) throws IOException { - if (value.hasArray()) { - writeRawBytes(value.array(), value.arrayOffset(), value.capacity()); - } else { - ByteBuffer duplicated = value.duplicate(); - duplicated.clear(); - writeRawBytesInternal(duplicated); - } - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeRawBytes(final ByteBuffer value) throws IOException; /** Write an embedded message field, including tag, to the stream. */ - public void writeMessage(final int fieldNumber, final MessageLite value) throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); - writeMessageNoTag(value); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeMessage(final int fieldNumber, final MessageLite value) + throws IOException; /** * 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 MessageLite value) - throws IOException { - writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); - writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); - writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value); - writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); - } + // 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. */ - public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value) - throws IOException { - writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); - writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); - writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value); - writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeRawMessageSetExtension(final int fieldNumber, final ByteString value) + throws IOException; // ----------------------------------------------------------------- /** 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); - } - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeInt32NoTag(final int value) throws IOException; /** Write a {@code uint32} field to the stream. */ - public void writeUInt32NoTag(final int value) throws IOException { - writeRawVarint32(value); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeUInt32NoTag(int value) throws IOException; /** Write a {@code sint32} field to the stream. */ - public void writeSInt32NoTag(final int value) throws IOException { - writeRawVarint32(encodeZigZag32(value)); + public final void writeSInt32NoTag(final int value) throws IOException { + writeUInt32NoTag(encodeZigZag32(value)); } /** Write a {@code fixed32} field to the stream. */ - public void writeFixed32NoTag(final int value) throws IOException { - writeRawLittleEndian32(value); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeFixed32NoTag(int value) throws IOException; /** Write a {@code sfixed32} field to the stream. */ - public void writeSFixed32NoTag(final int value) throws IOException { - writeRawLittleEndian32(value); + public final void writeSFixed32NoTag(final int value) throws IOException { + writeFixed32NoTag(value); } /** Write an {@code int64} field to the stream. */ - public void writeInt64NoTag(final long value) throws IOException { - writeRawVarint64(value); + public final void writeInt64NoTag(final long value) throws IOException { + writeUInt64NoTag(value); } /** Write a {@code uint64} field to the stream. */ - public void writeUInt64NoTag(final long value) throws IOException { - writeRawVarint64(value); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeUInt64NoTag(long value) throws IOException; /** Write a {@code sint64} field to the stream. */ - public void writeSInt64NoTag(final long value) throws IOException { - writeRawVarint64(encodeZigZag64(value)); + public final void writeSInt64NoTag(final long value) throws IOException { + writeUInt64NoTag(encodeZigZag64(value)); } /** Write a {@code fixed64} field to the stream. */ - public void writeFixed64NoTag(final long value) throws IOException { - writeRawLittleEndian64(value); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeFixed64NoTag(long value) throws IOException; /** Write a {@code sfixed64} field to the stream. */ - public void writeSFixed64NoTag(final long value) throws IOException { - writeRawLittleEndian64(value); + public final void writeSFixed64NoTag(final long value) throws IOException { + writeFixed64NoTag(value); } /** Write a {@code float} field to the stream. */ - public void writeFloatNoTag(final float value) throws IOException { - writeRawLittleEndian32(Float.floatToRawIntBits(value)); + public final void writeFloatNoTag(final float value) throws IOException { + writeFixed32NoTag(Float.floatToRawIntBits(value)); } /** Write a {@code double} field to the stream. */ - public void writeDoubleNoTag(final double value) throws IOException { - writeRawLittleEndian64(Double.doubleToRawLongBits(value)); + public final void writeDoubleNoTag(final double value) throws IOException { + writeFixed64NoTag(Double.doubleToRawLongBits(value)); } /** Write a {@code bool} field to the stream. */ - public void writeBoolNoTag(final boolean value) throws IOException { - writeRawByte(value ? 1 : 0); + public final void writeBoolNoTag(final boolean value) throws IOException { + write((byte) (value ? 1 : 0)); } /** * 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 void writeEnumNoTag(final int value) throws IOException { + public final void writeEnumNoTag(final int value) throws IOException { writeInt32NoTag(value); } /** Write a {@code string} field to the stream. */ // TODO(dweis): Document behavior on ill-formed UTF-16 input. - public void writeStringNoTag(final String value) throws IOException { - try { - efficientWriteStringNoTag(value); - } catch (UnpairedSurrogateException e) { - logger.log(Level.WARNING, - "Converting ill-formed UTF-16. Your Protocol Buffer will not round trip correctly!", e); - inefficientWriteStringNoTag(value); - } - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeStringNoTag(String value) throws IOException; /** Write a {@code bytes} field to the stream. */ - public void writeBytesNoTag(final ByteString value) throws IOException { - writeRawVarint32(value.size()); - writeRawBytes(value); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeBytesNoTag(final ByteString value) throws IOException; /** Write a {@code bytes} field to the stream. */ - public void writeByteArrayNoTag(final byte[] value) throws IOException { - writeRawVarint32(value.length); - writeRawBytes(value); + public final void writeByteArrayNoTag(final byte[] value) throws IOException { + writeByteArrayNoTag(value, 0, value.length); } /** Write an embedded message field to the stream. */ - public void writeMessageNoTag(final MessageLite value) throws IOException { - writeRawVarint32(value.getSerializedSize()); - value.writeTo(this); - } + // Abstract to avoid overhead of additional virtual method calls. + public abstract void writeMessageNoTag(final MessageLite value) throws IOException; + + //================================================================= + + @ExperimentalApi + @Override + public abstract void write(byte value) throws IOException; + + @ExperimentalApi + @Override + public abstract void write(byte[] value, int offset, int length) throws IOException; + + @ExperimentalApi + @Override + public abstract void writeLazy(byte[] value, int offset, int length) throws IOException; + + @Override + public abstract void write(ByteBuffer value) throws IOException; + + @ExperimentalApi + @Override + public abstract void writeLazy(ByteBuffer value) throws IOException; // ================================================================= // ================================================================= @@ -727,7 +661,7 @@ public final class CodedOutputStream { /** Compute the number of bytes that would be needed to encode a tag. */ public static int computeTagSize(final int fieldNumber) { - return computeRawVarint32Size(WireFormat.makeTag(fieldNumber, 0)); + return computeUInt32SizeNoTag(WireFormat.makeTag(fieldNumber, 0)); } /** @@ -736,10 +670,10 @@ public final class CodedOutputStream { */ public static int computeInt32SizeNoTag(final int value) { if (value >= 0) { - return computeRawVarint32Size(value); + return computeUInt32SizeNoTag(value); } else { // Must sign-extend. - return 10; + return MAX_VARINT_SIZE; } } @@ -748,7 +682,19 @@ public final class CodedOutputStream { * {@code uint32} field. */ public static int computeUInt32SizeNoTag(final int value) { - return computeRawVarint32Size(value); + if ((value & (~0 << 7)) == 0) { + return 1; + } + if ((value & (~0 << 14)) == 0) { + return 2; + } + if ((value & (~0 << 21)) == 0) { + return 3; + } + if ((value & (~0 << 28)) == 0) { + return 4; + } + return 5; } /** @@ -756,7 +702,7 @@ public final class CodedOutputStream { * {@code sint32} field. */ public static int computeSInt32SizeNoTag(final int value) { - return computeRawVarint32Size(encodeZigZag32(value)); + return computeUInt32SizeNoTag(encodeZigZag32(value)); } /** @@ -764,7 +710,7 @@ public final class CodedOutputStream { * {@code fixed32} field. */ public static int computeFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) { - return LITTLE_ENDIAN_32_SIZE; + return FIXED_32_SIZE; } /** @@ -772,7 +718,7 @@ public final class CodedOutputStream { * {@code sfixed32} field. */ public static int computeSFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) { - return LITTLE_ENDIAN_32_SIZE; + return FIXED_32_SIZE; } /** @@ -780,15 +726,33 @@ public final class CodedOutputStream { * {@code int64} field, including tag. */ public static int computeInt64SizeNoTag(final long value) { - return computeRawVarint64Size(value); + return computeUInt64SizeNoTag(value); } /** * 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); + public static int computeUInt64SizeNoTag(long value) { + // handle two popular special cases up front ... + if ((value & (~0L << 7)) == 0L) { + return 1; + } + if (value < 0L) { + return 10; + } + // ... leaving us with 8 remaining, which we can divide and conquer + int n = 2; + if ((value & (~0L << 35)) != 0L) { + n += 4; value >>>= 28; + } + if ((value & (~0L << 21)) != 0L) { + n += 2; value >>>= 14; + } + if ((value & (~0L << 14)) != 0L) { + n += 1; + } + return n; } /** @@ -796,7 +760,7 @@ public final class CodedOutputStream { * {@code sint64} field. */ public static int computeSInt64SizeNoTag(final long value) { - return computeRawVarint64Size(encodeZigZag64(value)); + return computeUInt64SizeNoTag(encodeZigZag64(value)); } /** @@ -804,7 +768,7 @@ public final class CodedOutputStream { * {@code fixed64} field. */ public static int computeFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) { - return LITTLE_ENDIAN_64_SIZE; + return FIXED_64_SIZE; } /** @@ -812,7 +776,7 @@ public final class CodedOutputStream { * {@code sfixed64} field. */ public static int computeSFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) { - return LITTLE_ENDIAN_64_SIZE; + return FIXED_64_SIZE; } /** @@ -820,7 +784,7 @@ public final class CodedOutputStream { * {@code float} field, including tag. */ public static int computeFloatSizeNoTag(@SuppressWarnings("unused") final float unused) { - return LITTLE_ENDIAN_32_SIZE; + return FIXED_32_SIZE; } /** @@ -828,7 +792,7 @@ public final class CodedOutputStream { * {@code double} field, including tag. */ public static int computeDoubleSizeNoTag(@SuppressWarnings("unused") final double unused) { - return LITTLE_ENDIAN_64_SIZE; + return FIXED_64_SIZE; } /** @@ -862,7 +826,7 @@ public final class CodedOutputStream { length = bytes.length; } - return computeRawVarint32Size(length) + length; + return computeLengthDelimitedFieldSize(length); } /** @@ -870,8 +834,7 @@ public final class CodedOutputStream { * message stored in lazy field. */ public static int computeLazyFieldSizeNoTag(final LazyFieldLite value) { - final int size = value.getSerializedSize(); - return computeRawVarint32Size(size) + size; + return computeLengthDelimitedFieldSize(value.getSerializedSize()); } /** @@ -879,7 +842,7 @@ public final class CodedOutputStream { * {@code bytes} field. */ public static int computeBytesSizeNoTag(final ByteString value) { - return computeRawVarint32Size(value.size()) + value.size(); + return computeLengthDelimitedFieldSize(value.size()); } /** @@ -887,7 +850,7 @@ public final class CodedOutputStream { * {@code bytes} field. */ public static int computeByteArraySizeNoTag(final byte[] value) { - return computeRawVarint32Size(value.length) + value.length; + return computeLengthDelimitedFieldSize(value.length); } /** @@ -895,7 +858,7 @@ public final class CodedOutputStream { * {@code bytes} field. */ public static int computeByteBufferSizeNoTag(final ByteBuffer value) { - return computeRawVarint32Size(value.capacity()) + value.capacity(); + return computeLengthDelimitedFieldSize(value.capacity()); } /** @@ -903,8 +866,11 @@ public final class CodedOutputStream { * message field. */ public static int computeMessageSizeNoTag(final MessageLite value) { - final int size = value.getSerializedSize(); - return computeRawVarint32Size(size) + size; + return computeLengthDelimitedFieldSize(value.getSerializedSize()); + } + + private static int computeLengthDelimitedFieldSize(int fieldLength) { + return computeUInt32SizeNoTag(fieldLength) + fieldLength; } /** @@ -943,25 +909,13 @@ public final class CodedOutputStream { * Flushes the stream and forces any buffered bytes to be written. This * does not flush the underlying OutputStream. */ - public void flush() throws IOException { - if (output != null) { - refreshBuffer(); - } - } + public abstract void flush() throws IOException; /** * If writing to a flat array, return the space left in the array. * Otherwise, throws {@code UnsupportedOperationException}. */ - public int spaceLeft() { - if (output == null) { - return limit - position; - } else { - throw new UnsupportedOperationException( - "spaceLeft() can only be called on CodedOutputStreams that are " - + "writing to a flat array."); - } - } + public abstract int spaceLeft(); /** * Verifies that {@link #spaceLeft()} returns zero. It's common to create @@ -970,7 +924,7 @@ public final class CodedOutputStream { * after writing verifies that the message was actually as big as expected, * which can help catch bugs. */ - public void checkNoSpaceLeft() { + public final void checkNoSpaceLeft() { if (spaceLeft() != 0) { throw new IllegalStateException("Did not write as much data as expected."); } @@ -1001,183 +955,31 @@ public final class CodedOutputStream { * returned value is not guaranteed to be accurate if exceptions have been * found in the middle of writing. */ - public int getTotalBytesWritten() { - return totalBytesWritten; - } + public abstract int getTotalBytesWritten(); // ================================================================= - /** - * Internal helper that writes the current buffer to the output. The - * buffer position is reset to its initial value when this returns. - */ - private void refreshBuffer() throws IOException { - if (output == null) { - // We're writing to a single buffer. - throw new OutOfSpaceException(); - } + /** Write a {@code bytes} field to the stream. Visible for testing. */ + abstract void writeByteArrayNoTag(final byte[] value, final int offset, final int length) + throws IOException; - // Since we have an output stream, this is our buffer - // and buffer offset == 0 - output.write(buffer, 0, position); - position = 0; - } + 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); - /** Write a {@code string} field to the stream. */ - private void inefficientWriteStringNoTag(final String value) throws IOException { // 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 // array and then copy. // TODO(dweis): Consider using nio Charset methods instead. final byte[] bytes = value.getBytes(Internal.UTF_8); - writeRawVarint32(bytes.length); - writeRawBytes(bytes); - } - - /** - * Write a {@code string} field to the stream efficiently. If the {@code string} is malformed, - * this method rolls back its changes and throws an {@link UnpairedSurrogateException} with the - * intent that the caller will catch and retry with {@link #inefficientWriteStringNoTag(String)}. - * - * @param value the string to write to the stream - * - * @throws UnpairedSurrogateException when {@code value} is ill-formed UTF-16. - */ - private void efficientWriteStringNoTag(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. We take advantage of this in both branches below. - final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR; - final int maxLengthVarIntSize = computeRawVarint32Size(maxLength); - - // If we are streaming and the potential length is too big to fit in our buffer, we take the - // slower path. Otherwise, we're good to try the fast path. - if (output != null && maxLengthVarIntSize + maxLength > limit - position) { - // Allocate a byte[] that we know can fit the string and encode into it. String.getBytes() - // does the same internally and then does *another copy* to return a byte[] of exactly the - // right size. We can skip that copy and just writeRawBytes up to the actualLength of the - // UTF-8 encoded bytes. - final byte[] encodedBytes = new byte[maxLength]; - int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength); - writeRawVarint32(actualLength); - writeRawBytes(encodedBytes, 0, actualLength); - } else { - // Optimize for the case where we know this length results in a constant varint length as this - // saves a pass for measuring the length of the string. - final int minLengthVarIntSize = computeRawVarint32Size(value.length()); - int oldPosition = position; - final int length; - try { - if (minLengthVarIntSize == maxLengthVarIntSize) { - position = oldPosition + minLengthVarIntSize; - int newPosition = Utf8.encode(value, buffer, position, limit - position); - // Since this class is stateful and tracks the position, we rewind and store the state, - // prepend the length, then reset it back to the end of the string. - position = oldPosition; - length = newPosition - oldPosition - minLengthVarIntSize; - writeRawVarint32(length); - position = newPosition; - } else { - length = Utf8.encodedLength(value); - writeRawVarint32(length); - position = Utf8.encode(value, buffer, position, limit - position); - } - } catch (UnpairedSurrogateException e) { - // Be extra careful and restore the original position for retrying the write with the less - // efficient path. - position = oldPosition; - throw e; - } catch (ArrayIndexOutOfBoundsException e) { - throw new OutOfSpaceException(e); - } - totalBytesWritten += length; - } - } - - /** Write a ByteBuffer that isn't backed by an array. */ - private void writeRawBytesInternal(final ByteBuffer value) throws IOException { - int length = value.remaining(); - if (limit - position >= length) { - // We have room in the current buffer. - value.get(buffer, position, length); - position += length; - totalBytesWritten += length; - } else { - // Write extends past current buffer. Fill the rest of this buffer and - // flush. - final int bytesWritten = limit - position; - value.get(buffer, position, bytesWritten); - length -= bytesWritten; - position = limit; - totalBytesWritten += bytesWritten; - refreshBuffer(); - - // Now deal with the rest. - // Since we have an output stream, this is our buffer - // and buffer offset == 0 - while (length > limit) { - // Copy data into the buffer before writing it to OutputStream. - // TODO(xiaofeng): Introduce ZeroCopyOutputStream to avoid this copy. - value.get(buffer, 0, limit); - output.write(buffer, 0, limit); - length -= limit; - totalBytesWritten += limit; - } - value.get(buffer, 0, length); - position = length; - totalBytesWritten += length; - } - } - - /** Write a {@code bytes} field to the stream. Visible for testing. */ - void writeByteArrayNoTag(final byte[] value, final int offset, final int length) - throws IOException { - writeRawVarint32(length); - writeRawBytes(value, offset, length); - } - - /** - * Write a {@code bytes} field 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 writeByteBufferNoTag(byteBuffer.slice())}. - */ - private void writeByteBufferNoTag(final ByteBuffer value) throws IOException { - writeRawVarint32(value.capacity()); - writeRawBytes(value); - } - - /** Write part of a byte string. */ - private void writeRawBytes(final ByteString value, int offset, int length) throws IOException { - if (limit - position >= length) { - // We have room in the current buffer. - value.copyTo(buffer, offset, position, length); - position += length; - totalBytesWritten += length; - } else { - // Write extends past current buffer. Fill the rest of this buffer and - // flush. - final int bytesWritten = limit - position; - value.copyTo(buffer, offset, position, bytesWritten); - offset += bytesWritten; - length -= bytesWritten; - position = limit; - totalBytesWritten += bytesWritten; - 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. - value.copyTo(buffer, offset, 0, length); - position = length; - } else { - value.writeTo(output, offset, length); - } - totalBytesWritten += length; + try { + writeUInt32NoTag(bytes.length); + writeLazy(bytes, 0, bytes.length); + } catch (IndexOutOfBoundsException e) { + throw new OutOfSpaceException(e); + } catch (OutOfSpaceException e) { + throw e; } } @@ -1189,7 +991,7 @@ public final class CodedOutputStream { * @deprecated groups are deprecated. */ @Deprecated - public void writeGroup(final int fieldNumber, final MessageLite value) throws IOException { + public final void writeGroup(final int fieldNumber, final MessageLite value) throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP); writeGroupNoTag(value); writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP); @@ -1201,7 +1003,7 @@ public final class CodedOutputStream { * @deprecated groups are deprecated. */ @Deprecated - public void writeGroupNoTag(final MessageLite value) throws IOException { + public final void writeGroupNoTag(final MessageLite value) throws IOException { value.writeTo(this); } @@ -1232,16 +1034,8 @@ public final class CodedOutputStream { * @deprecated use {@link #writeUInt32NoTag} instead. */ @Deprecated - public void writeRawVarint32(int value) throws IOException { - while (true) { - if ((value & ~0x7F) == 0) { - writeRawByte(value); - return; - } else { - writeRawByte((value & 0x7F) | 0x80); - value >>>= 7; - } - } + public final void writeRawVarint32(int value) throws IOException { + writeUInt32NoTag(value); } /** @@ -1250,16 +1044,8 @@ public final class CodedOutputStream { * @deprecated use {@link #writeUInt64NoTag} instead. */ @Deprecated - 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; - } - } + public final void writeRawVarint64(long value) throws IOException { + writeUInt64NoTag(value); } /** @@ -1271,19 +1057,7 @@ public final class CodedOutputStream { */ @Deprecated public static int computeRawVarint32Size(final int value) { - if ((value & (~0 << 7)) == 0) { - return 1; - } - if ((value & (~0 << 14)) == 0) { - return 2; - } - if ((value & (~0 << 21)) == 0) { - return 3; - } - if ((value & (~0 << 28)) == 0) { - return 4; - } - return 5; + return computeUInt32SizeNoTag(value); } /** @@ -1293,27 +1067,7 @@ public final class CodedOutputStream { */ @Deprecated public static int computeRawVarint64Size(long value) { - // handle two popular special cases up front ... - if ((value & (~0L << 7)) == 0L) { - return 1; - } - if (value < 0L) { - return 10; - } - // ... leaving us with 8 remaining, which we can divide and conquer - int n = 2; - if ((value & (~0L << 35)) != 0L) { - n += 4; - value >>>= 28; - } - if ((value & (~0L << 21)) != 0L) { - n += 2; - value >>>= 14; - } - if ((value & (~0L << 14)) != 0L) { - n += 1; - } - return n; + return computeUInt64SizeNoTag(value); } /** @@ -1322,11 +1076,8 @@ public final class CodedOutputStream { * @deprecated Use {@link #writeFixed32NoTag} instead. */ @Deprecated - public void writeRawLittleEndian32(final int value) throws IOException { - writeRawByte((value) & 0xFF); - writeRawByte((value >> 8) & 0xFF); - writeRawByte((value >> 16) & 0xFF); - writeRawByte((value >> 24) & 0xFF); + public final void writeRawLittleEndian32(final int value) throws IOException { + writeFixed32NoTag(value); } /** @@ -1335,14 +1086,1579 @@ public final class CodedOutputStream { * @deprecated Use {@link #writeFixed64NoTag} instead. */ @Deprecated - public void writeRawLittleEndian64(final long value) throws IOException { - writeRawByte((int) (value) & 0xFF); - writeRawByte((int) (value >> 8) & 0xFF); - writeRawByte((int) (value >> 16) & 0xFF); - writeRawByte((int) (value >> 24) & 0xFF); - writeRawByte((int) (value >> 32) & 0xFF); - writeRawByte((int) (value >> 40) & 0xFF); - writeRawByte((int) (value >> 48) & 0xFF); - writeRawByte((int) (value >> 56) & 0xFF); + public final void writeRawLittleEndian64(final long value) throws IOException { + writeFixed64NoTag(value); + } + + // ================================================================= + + /** + * A {@link CodedOutputStream} that writes directly to a byte array. + */ + private static class ArrayEncoder extends CodedOutputStream { + private final byte[] buffer; + private final int offset; + private final int limit; + private int position; + + ArrayEncoder(byte[] buffer, int offset, int length) { + if (buffer == null) { + 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)); + } + this.buffer = buffer; + this.offset = offset; + position = offset; + limit = offset + length; + } + + @Override + public final void writeTag(final int fieldNumber, final int wireType) throws IOException { + writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType)); + } + + @Override + public final void writeInt32(final int fieldNumber, final int value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + writeInt32NoTag(value); + } + + @Override + public final void writeUInt32(final int fieldNumber, final int value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + writeUInt32NoTag(value); + } + + @Override + public final void writeFixed32(final int fieldNumber, final int value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); + writeFixed32NoTag(value); + } + + @Override + public final void writeUInt64(final int fieldNumber, final long value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + writeUInt64NoTag(value); + } + + @Override + public final void writeFixed64(final int fieldNumber, final long value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); + writeFixed64NoTag(value); + } + + @Override + public final void writeBool(final int fieldNumber, final boolean value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + write((byte) (value ? 1 : 0)); + } + + @Override + public final void writeString(final int fieldNumber, final String value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeStringNoTag(value); + } + + @Override + public final void writeBytes(final int fieldNumber, final ByteString value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeBytesNoTag(value); + } + + @Override + public final void writeByteArray(final int fieldNumber, final byte[] value) throws IOException { + writeByteArray(fieldNumber, value, 0, value.length); + } + + @Override + public final void writeByteArray( + final int fieldNumber, final byte[] value, final int offset, final int length) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeByteArrayNoTag(value, offset, length); + } + + @Override + public final void writeByteBuffer(final int fieldNumber, final ByteBuffer value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeUInt32NoTag(value.capacity()); + writeRawBytes(value); + } + + @Override + public final void writeBytesNoTag(final ByteString value) throws IOException { + writeUInt32NoTag(value.size()); + value.writeTo(this); + } + + @Override + public final void writeByteArrayNoTag(final byte[] value, int offset, int length) + throws IOException { + writeUInt32NoTag(length); + write(value, offset, length); + } + + @Override + public final void writeRawBytes(final ByteBuffer value) throws IOException { + if (value.hasArray()) { + write(value.array(), value.arrayOffset(), value.capacity()); + } else { + ByteBuffer duplicated = value.duplicate(); + duplicated.clear(); + write(duplicated); + } + } + + @Override + public final void writeMessage(final int fieldNumber, final MessageLite value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeMessageNoTag(value); + } + + @Override + public final void writeMessageSetExtension(final int fieldNumber, final MessageLite value) + throws IOException { + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); + writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); + writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value); + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); + } + + @Override + public final void writeRawMessageSetExtension(final int fieldNumber, final ByteString value) + throws IOException { + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); + writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); + writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value); + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); + } + + @Override + public final void writeMessageNoTag(final MessageLite value) throws IOException { + writeUInt32NoTag(value.getSerializedSize()); + value.writeTo(this); + } + + @Override + public final void write(byte value) throws IOException { + try { + buffer[position++] = value; + } catch (IndexOutOfBoundsException e) { + throw new OutOfSpaceException(new IndexOutOfBoundsException( + String.format("Pos: %d, limit: %d, len: %d", position, limit, 1))); + } + } + + @Override + public final void writeInt32NoTag(int value) throws IOException { + if (value >= 0) { + writeUInt32NoTag(value); + } else { + // Must sign-extend. + writeUInt64NoTag(value); + } + } + + @Override + public final void writeUInt32NoTag(int value) throws IOException { + if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) { + long pos = ARRAY_BASE_OFFSET + position; + while (true) { + if ((value & ~0x7F) == 0) { + UNSAFE.putByte(buffer, pos++, (byte) value); + position++; + return; + } else { + UNSAFE.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80)); + position++; + value >>>= 7; + } + } + } else { + try { + while (true) { + if ((value & ~0x7F) == 0) { + buffer[position++] = (byte) value; + return; + } else { + buffer[position++] = (byte) ((value & 0x7F) | 0x80); + value >>>= 7; + } + } + } catch (IndexOutOfBoundsException e) { + throw new OutOfSpaceException( + new IndexOutOfBoundsException( + String.format("Pos: %d, limit: %d, len: %d", position, limit, 1))); + } + } + } + + @Override + public final void writeFixed32NoTag(int value) throws IOException { + try { + buffer[position++] = (byte) (value & 0xFF); + buffer[position++] = (byte) ((value >> 8) & 0xFF); + buffer[position++] = (byte) ((value >> 16) & 0xFF); + buffer[position++] = (byte) ((value >> 24) & 0xFF); + } catch (IndexOutOfBoundsException e) { + throw new OutOfSpaceException( + new IndexOutOfBoundsException( + String.format("Pos: %d, limit: %d, len: %d", position, limit, 1))); + } + } + + @Override + public final void writeUInt64NoTag(long value) throws IOException { + if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) { + long pos = ARRAY_BASE_OFFSET + position; + while (true) { + if ((value & ~0x7FL) == 0) { + UNSAFE.putByte(buffer, pos++, (byte) value); + position++; + return; + } else { + UNSAFE.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80)); + position++; + value >>>= 7; + } + } + } else { + try { + while (true) { + if ((value & ~0x7FL) == 0) { + buffer[position++] = (byte) value; + return; + } else { + buffer[position++] = (byte) (((int) value & 0x7F) | 0x80); + value >>>= 7; + } + } + } catch (IndexOutOfBoundsException e) { + throw new OutOfSpaceException( + new IndexOutOfBoundsException( + String.format("Pos: %d, limit: %d, len: %d", position, limit, 1))); + } + } + } + + @Override + public final void writeFixed64NoTag(long value) throws IOException { + try { + buffer[position++] = (byte) ((int) (value) & 0xFF); + buffer[position++] = (byte) ((int) (value >> 8) & 0xFF); + buffer[position++] = (byte) ((int) (value >> 16) & 0xFF); + buffer[position++] = (byte) ((int) (value >> 24) & 0xFF); + buffer[position++] = (byte) ((int) (value >> 32) & 0xFF); + buffer[position++] = (byte) ((int) (value >> 40) & 0xFF); + buffer[position++] = (byte) ((int) (value >> 48) & 0xFF); + buffer[position++] = (byte) ((int) (value >> 56) & 0xFF); + } catch (IndexOutOfBoundsException e) { + throw new OutOfSpaceException( + new IndexOutOfBoundsException( + String.format("Pos: %d, limit: %d, len: %d", position, limit, 1))); + } + } + + @Override + public final void write(byte[] value, int offset, int length) throws IOException { + try { + System.arraycopy(value, offset, buffer, position, length); + position += length; + } catch (IndexOutOfBoundsException e) { + throw new OutOfSpaceException( + new IndexOutOfBoundsException( + String.format("Pos: %d, limit: %d, len: %d", position, limit, length))); + } + } + + @Override + public final void writeLazy(byte[] value, int offset, int length) throws IOException { + write(value, offset, length); + } + + @Override + public final void write(ByteBuffer value) throws IOException { + final int length = value.remaining(); + try { + value.get(buffer, position, length); + position += length; + } catch (IndexOutOfBoundsException e) { + throw new OutOfSpaceException( + new IndexOutOfBoundsException( + String.format("Pos: %d, limit: %d, len: %d", position, limit, length))); + } + } + + @Override + public final void writeLazy(ByteBuffer value) throws IOException { + write(value); + } + + @Override + public final void writeStringNoTag(String value) throws IOException { + final int oldPosition = position; + try { + // 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. We take advantage of this in both branches below. + final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR; + final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength); + final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length()); + if (minLengthVarIntSize == maxLengthVarIntSize) { + position = oldPosition + minLengthVarIntSize; + int newPosition = Utf8.encode(value, buffer, position, spaceLeft()); + // Since this class is stateful and tracks the position, we rewind and store the state, + // prepend the length, then reset it back to the end of the string. + position = oldPosition; + int length = newPosition - oldPosition - minLengthVarIntSize; + writeUInt32NoTag(length); + position = newPosition; + } else { + int length = Utf8.encodedLength(value); + writeUInt32NoTag(length); + position = Utf8.encode(value, buffer, position, spaceLeft()); + } + } catch (UnpairedSurrogateException e) { + // Roll back the change - we fall back to inefficient path. + position = oldPosition; + + // TODO(nathanmittler): We should throw an IOException here instead. + inefficientWriteStringNoTag(value, e); + } catch (IndexOutOfBoundsException e) { + throw new OutOfSpaceException(e); + } + } + + @Override + public void flush() { + // Do nothing. + } + + @Override + public final int spaceLeft() { + return limit - position; + } + + @Override + public final int getTotalBytesWritten() { + return position - offset; + } + } + + /** + * 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 NioHeapEncoder extends ArrayEncoder { + private final ByteBuffer byteBuffer; + private int initialPosition; + + NioHeapEncoder(ByteBuffer byteBuffer) { + super(byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position(), + byteBuffer.remaining()); + this.byteBuffer = byteBuffer; + this.initialPosition = byteBuffer.position(); + } + + @Override + public void flush() { + // Update the position on the buffer. + byteBuffer.position(initialPosition + getTotalBytesWritten()); + } + } + + /** + * A {@link CodedOutputStream} that writes directly to a {@link ByteBuffer}. + */ + private static final class NioEncoder extends CodedOutputStream { + private final ByteBuffer originalBuffer; + private final ByteBuffer buffer; + private final int initialPosition; + + NioEncoder(ByteBuffer buffer) { + this.originalBuffer = buffer; + this.buffer = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN); + initialPosition = buffer.position(); + } + + @Override + public void writeTag(final int fieldNumber, final int wireType) throws IOException { + writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType)); + } + + @Override + public void writeInt32(final int fieldNumber, final int value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + writeInt32NoTag(value); + } + + @Override + public void writeUInt32(final int fieldNumber, final int value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + writeUInt32NoTag(value); + } + + @Override + public void writeFixed32(final int fieldNumber, final int value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); + writeFixed32NoTag(value); + } + + @Override + public void writeUInt64(final int fieldNumber, final long value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + writeUInt64NoTag(value); + } + + @Override + public void writeFixed64(final int fieldNumber, final long value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); + writeFixed64NoTag(value); + } + + @Override + public void writeBool(final int fieldNumber, final boolean value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + write((byte) (value ? 1 : 0)); + } + + @Override + public void writeString(final int fieldNumber, final String value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeStringNoTag(value); + } + + @Override + public void writeBytes(final int fieldNumber, final ByteString value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeBytesNoTag(value); + } + + @Override + public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException { + writeByteArray(fieldNumber, value, 0, value.length); + } + + @Override + public void writeByteArray( + final int fieldNumber, final byte[] value, final int offset, final int length) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeByteArrayNoTag(value, offset, length); + } + + @Override + 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 { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeMessageNoTag(value); + } + + @Override + public void writeMessageSetExtension(final int fieldNumber, final MessageLite value) + throws IOException { + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); + writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); + writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value); + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); + } + + @Override + public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value) + throws IOException { + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); + writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); + writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value); + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); + } + + @Override + public void writeMessageNoTag(final MessageLite value) throws IOException { + writeUInt32NoTag(value.getSerializedSize()); + value.writeTo(this); + } + + @Override + public void write(byte value) throws IOException { + try { + buffer.put(value); + } catch (BufferOverflowException e) { + throw new OutOfSpaceException(e); + } + } + + @Override + public void writeBytesNoTag(final ByteString value) throws IOException { + writeUInt32NoTag(value.size()); + value.writeTo(this); + } + + @Override + public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException { + writeUInt32NoTag(length); + write(value, offset, length); + } + + @Override + public void writeRawBytes(final ByteBuffer value) throws IOException { + if (value.hasArray()) { + write(value.array(), value.arrayOffset(), value.capacity()); + } else { + ByteBuffer duplicated = value.duplicate(); + duplicated.clear(); + write(duplicated); + } + } + + @Override + public void writeInt32NoTag(int value) throws IOException { + if (value >= 0) { + writeUInt32NoTag(value); + } else { + // Must sign-extend. + writeUInt64NoTag(value); + } + } + + @Override + public void writeUInt32NoTag(int value) throws IOException { + try { + while (true) { + if ((value & ~0x7F) == 0) { + buffer.put((byte) value); + return; + } else { + buffer.put((byte) ((value & 0x7F) | 0x80)); + value >>>= 7; + } + } + } catch (BufferOverflowException e) { + throw new OutOfSpaceException(e); + } + } + + @Override + public void writeFixed32NoTag(int value) throws IOException { + try { + buffer.putInt(value); + } catch (BufferOverflowException e) { + throw new OutOfSpaceException(e); + } + } + + @Override + public void writeUInt64NoTag(long value) throws IOException { + try { + while (true) { + if ((value & ~0x7FL) == 0) { + buffer.put((byte) value); + return; + } else { + buffer.put((byte) (((int) value & 0x7F) | 0x80)); + value >>>= 7; + } + } + } catch (BufferOverflowException e) { + throw new OutOfSpaceException(e); + } + } + + @Override + public void writeFixed64NoTag(long value) throws IOException { + try { + buffer.putLong(value); + } catch (BufferOverflowException e) { + throw new OutOfSpaceException(e); + } + } + + @Override + public void write(byte[] value, int offset, int length) throws IOException { + try { + buffer.put(value, offset, length); + } catch (IndexOutOfBoundsException e) { + throw new OutOfSpaceException(e); + } catch (BufferOverflowException e) { + throw new OutOfSpaceException(e); + } + } + + @Override + public void writeLazy(byte[] value, int offset, int length) throws IOException { + write(value, offset, length); + } + + @Override + public void write(ByteBuffer value) throws IOException { + try { + buffer.put(value); + } catch (BufferOverflowException e) { + throw new OutOfSpaceException(e); + } + } + + @Override + public void writeLazy(ByteBuffer value) throws IOException { + write(value); + } + + @Override + public void writeStringNoTag(String value) throws IOException { + final int startPos = buffer.position(); + try { + // 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. We take advantage of this in both branches below. + final int maxEncodedSize = value.length() * Utf8.MAX_BYTES_PER_CHAR; + final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxEncodedSize); + final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length()); + if (minLengthVarIntSize == maxLengthVarIntSize) { + // Save the current position and increment past the length field. We'll come back + // and write the length field after the encoding is complete. + final int startOfBytes = buffer.position() + minLengthVarIntSize; + buffer.position(startOfBytes); + + // Encode the string. + encode(value); + + // Now go back to the beginning and write the length. + int endOfBytes = buffer.position(); + buffer.position(startPos); + writeUInt32NoTag(endOfBytes - startOfBytes); + + // Reposition the buffer past the written data. + buffer.position(endOfBytes); + } else { + final int length = Utf8.encodedLength(value); + writeUInt32NoTag(length); + encode(value); + } + } catch (UnpairedSurrogateException e) { + // Roll back the change and convert to an IOException. + buffer.position(startPos); + + // TODO(nathanmittler): We should throw an IOException here instead. + inefficientWriteStringNoTag(value, e); + } catch (IllegalArgumentException e) { + // Thrown by buffer.position() if out of range. + throw new OutOfSpaceException(e); + } + } + + @Override + public void flush() { + // Update the position of the original buffer. + originalBuffer.position(buffer.position()); + } + + @Override + public int spaceLeft() { + return buffer.remaining(); + } + + @Override + public int getTotalBytesWritten() { + return buffer.position() - initialPosition; + } + + private void encode(String value) throws IOException { + try { + Utf8.encodeUtf8(value, buffer); + } catch (IndexOutOfBoundsException e) { + throw new OutOfSpaceException(e); + } + } + } + + /** + * Abstract base class for buffered encoders. + */ + private abstract static class AbstractBufferedEncoder extends CodedOutputStream { + final byte[] buffer; + final int limit; + int position; + int totalBytesWritten; + + AbstractBufferedEncoder(int bufferSize) { + if (bufferSize < 0) { + throw new IllegalArgumentException("bufferSize must be >= 0"); + } + // As an optimization, we require that the buffer be able to store at least 2 + // varints so that we can buffer any integer write (tag + value). This reduces the + // number of range checks for a single write to 1 (i.e. if there is not enough space + // to buffer the tag+value, flush and then buffer it). + this.buffer = new byte[max(bufferSize, MAX_VARINT_SIZE * 2)]; + this.limit = buffer.length; + } + + @Override + public final int spaceLeft() { + throw new UnsupportedOperationException( + "spaceLeft() can only be called on CodedOutputStreams that are " + + "writing to a flat array or ByteBuffer."); + } + + @Override + public final int getTotalBytesWritten() { + return totalBytesWritten; + } + + /** + * This method does not perform bounds checking on the array. Checking array bounds is the + * responsibility of the caller. + */ + final void buffer(byte value) { + buffer[position++] = value; + totalBytesWritten++; + } + + /** + * This method does not perform bounds checking on the array. Checking array bounds is the + * responsibility of the caller. + */ + final void bufferTag(final int fieldNumber, final int wireType) { + bufferUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType)); + } + + /** + * This method does not perform bounds checking on the array. Checking array bounds is the + * responsibility of the caller. + */ + final void bufferInt32NoTag(final int value) { + if (value >= 0) { + bufferUInt32NoTag(value); + } else { + // Must sign-extend. + bufferUInt64NoTag(value); + } + } + + /** + * This method does not perform bounds checking on the array. Checking array bounds is the + * responsibility of the caller. + */ + final void bufferUInt32NoTag(int value) { + if (HAS_UNSAFE_ARRAY_OPERATIONS) { + final long originalPos = ARRAY_BASE_OFFSET + position; + long pos = originalPos; + while (true) { + if ((value & ~0x7F) == 0) { + UNSAFE.putByte(buffer, pos++, (byte) value); + break; + } else { + UNSAFE.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80)); + value >>>= 7; + } + } + int delta = (int) (pos - originalPos); + position += delta; + totalBytesWritten += delta; + } else { + while (true) { + if ((value & ~0x7F) == 0) { + buffer[position++] = (byte) value; + totalBytesWritten++; + return; + } else { + buffer[position++] = (byte) ((value & 0x7F) | 0x80); + totalBytesWritten++; + value >>>= 7; + } + } + } + } + + /** + * This method does not perform bounds checking on the array. Checking array bounds is the + * responsibility of the caller. + */ + final void bufferUInt64NoTag(long value) { + if (HAS_UNSAFE_ARRAY_OPERATIONS) { + final long originalPos = ARRAY_BASE_OFFSET + position; + long pos = originalPos; + while (true) { + if ((value & ~0x7FL) == 0) { + UNSAFE.putByte(buffer, pos++, (byte) value); + break; + } else { + UNSAFE.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80)); + value >>>= 7; + } + } + int delta = (int) (pos - originalPos); + position += delta; + totalBytesWritten += delta; + } else { + while (true) { + if ((value & ~0x7FL) == 0) { + buffer[position++] = (byte) value; + totalBytesWritten++; + return; + } else { + buffer[position++] = (byte) (((int) value & 0x7F) | 0x80); + totalBytesWritten++; + value >>>= 7; + } + } + } + } + + /** + * This method does not perform bounds checking on the array. Checking array bounds is the + * responsibility of the caller. + */ + final void bufferFixed32NoTag(int value) { + buffer[position++] = (byte) (value & 0xFF); + buffer[position++] = (byte) ((value >> 8) & 0xFF); + buffer[position++] = (byte) ((value >> 16) & 0xFF); + buffer[position++] = (byte) ((value >> 24) & 0xFF); + totalBytesWritten += FIXED_32_SIZE; + } + + /** + * This method does not perform bounds checking on the array. Checking array bounds is the + * responsibility of the caller. + */ + final void bufferFixed64NoTag(long value) { + buffer[position++] = (byte) (value & 0xFF); + buffer[position++] = (byte) ((value >> 8) & 0xFF); + buffer[position++] = (byte) ((value >> 16) & 0xFF); + buffer[position++] = (byte) ((value >> 24) & 0xFF); + buffer[position++] = (byte) ((int) (value >> 32) & 0xFF); + buffer[position++] = (byte) ((int) (value >> 40) & 0xFF); + buffer[position++] = (byte) ((int) (value >> 48) & 0xFF); + buffer[position++] = (byte) ((int) (value >> 56) & 0xFF); + totalBytesWritten += FIXED_64_SIZE; + } + } + + /** + * 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}. + */ + private static final class ByteOutputEncoder extends AbstractBufferedEncoder { + private final ByteOutput out; + + ByteOutputEncoder(ByteOutput out, int bufferSize) { + super(bufferSize); + if (out == null) { + throw new NullPointerException("out"); + } + this.out = out; + } + + @Override + public void writeTag(final int fieldNumber, final int wireType) throws IOException { + writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType)); + } + + @Override + public void writeInt32(final int fieldNumber, final int value) throws IOException { + flushIfNotAvailable(MAX_VARINT_SIZE * 2); + bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + bufferInt32NoTag(value); + } + + @Override + public void writeUInt32(final int fieldNumber, final int value) throws IOException { + flushIfNotAvailable(MAX_VARINT_SIZE * 2); + bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + bufferUInt32NoTag(value); + } + + @Override + public void writeFixed32(final int fieldNumber, final int value) throws IOException { + flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_32_SIZE); + bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); + bufferFixed32NoTag(value); + } + + @Override + public void writeUInt64(final int fieldNumber, final long value) throws IOException { + flushIfNotAvailable(MAX_VARINT_SIZE * 2); + bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + bufferUInt64NoTag(value); + } + + @Override + public void writeFixed64(final int fieldNumber, final long value) throws IOException { + flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_64_SIZE); + bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); + bufferFixed64NoTag(value); + } + + @Override + public void writeBool(final int fieldNumber, final boolean value) throws IOException { + flushIfNotAvailable(MAX_VARINT_SIZE + 1); + bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + buffer((byte) (value ? 1 : 0)); + } + + @Override + public void writeString(final int fieldNumber, final String value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeStringNoTag(value); + } + + @Override + public void writeBytes(final int fieldNumber, final ByteString value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeBytesNoTag(value); + } + + @Override + public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException { + writeByteArray(fieldNumber, value, 0, value.length); + } + + @Override + public void writeByteArray( + final int fieldNumber, final byte[] value, final int offset, final int length) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeByteArrayNoTag(value, offset, length); + } + + @Override + 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 writeBytesNoTag(final ByteString value) throws IOException { + writeUInt32NoTag(value.size()); + value.writeTo(this); + } + + @Override + public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException { + writeUInt32NoTag(length); + write(value, offset, length); + } + + @Override + public void writeRawBytes(final ByteBuffer value) throws IOException { + if (value.hasArray()) { + write(value.array(), value.arrayOffset(), value.capacity()); + } else { + ByteBuffer duplicated = value.duplicate(); + duplicated.clear(); + write(duplicated); + } + } + + @Override + public void writeMessage(final int fieldNumber, final MessageLite value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeMessageNoTag(value); + } + + @Override + public void writeMessageSetExtension(final int fieldNumber, final MessageLite value) + throws IOException { + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); + writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); + writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value); + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); + } + + @Override + public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value) + throws IOException { + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); + writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); + writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value); + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); + } + + @Override + public void writeMessageNoTag(final MessageLite value) throws IOException { + writeUInt32NoTag(value.getSerializedSize()); + value.writeTo(this); + } + + @Override + public void write(byte value) throws IOException { + if (position == limit) { + doFlush(); + } + + buffer(value); + } + + @Override + public void writeInt32NoTag(int value) throws IOException { + if (value >= 0) { + writeUInt32NoTag(value); + } else { + // Must sign-extend. + writeUInt64NoTag(value); + } + } + + @Override + public void writeUInt32NoTag(int value) throws IOException { + flushIfNotAvailable(MAX_VARINT_SIZE); + bufferUInt32NoTag(value); + } + + @Override + public void writeFixed32NoTag(final int value) throws IOException { + flushIfNotAvailable(FIXED_32_SIZE); + bufferFixed32NoTag(value); + } + + @Override + public void writeUInt64NoTag(long value) throws IOException { + flushIfNotAvailable(MAX_VARINT_SIZE); + bufferUInt64NoTag(value); + } + + @Override + public void writeFixed64NoTag(final long value) throws IOException { + flushIfNotAvailable(FIXED_64_SIZE); + bufferFixed64NoTag(value); + } + + @Override + public void writeStringNoTag(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. We take advantage of this in both branches below. + final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR; + final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength); + + // If we are streaming and the potential length is too big to fit in our buffer, we take the + // slower path. + if (maxLengthVarIntSize + maxLength > limit) { + // Allocate a byte[] that we know can fit the string and encode into it. String.getBytes() + // does the same internally and then does *another copy* to return a byte[] of exactly the + // right size. We can skip that copy and just writeRawBytes up to the actualLength of the + // UTF-8 encoded bytes. + final byte[] encodedBytes = new byte[maxLength]; + int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength); + writeUInt32NoTag(actualLength); + writeLazy(encodedBytes, 0, actualLength); + return; + } + + // Fast path: we have enough space available in our buffer for the string... + if (maxLengthVarIntSize + maxLength > limit - position) { + // Flush to free up space. + doFlush(); + } + + final int oldPosition = position; + try { + // Optimize for the case where we know this length results in a constant varint length as + // this saves a pass for measuring the length of the string. + final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length()); + + if (minLengthVarIntSize == maxLengthVarIntSize) { + position = oldPosition + minLengthVarIntSize; + int newPosition = Utf8.encode(value, buffer, position, limit - position); + // Since this class is stateful and tracks the position, we rewind and store the state, + // prepend the length, then reset it back to the end of the string. + position = oldPosition; + int length = newPosition - oldPosition - minLengthVarIntSize; + bufferUInt32NoTag(length); + position = newPosition; + totalBytesWritten += length; + } else { + int length = Utf8.encodedLength(value); + bufferUInt32NoTag(length); + position = Utf8.encode(value, buffer, position, length); + totalBytesWritten += length; + } + } catch (UnpairedSurrogateException e) { + // Roll back the change and convert to an IOException. + totalBytesWritten -= position - oldPosition; + position = oldPosition; + + // TODO(nathanmittler): We should throw an IOException here instead. + inefficientWriteStringNoTag(value, e); + } catch (IndexOutOfBoundsException e) { + throw new OutOfSpaceException(e); + } + } + + @Override + public void flush() throws IOException { + if (position > 0) { + // Flush the buffer. + doFlush(); + } + } + + @Override + public void write(byte[] value, int offset, int length) throws IOException { + flush(); + out.write(value, offset, length); + totalBytesWritten += length; + } + + @Override + public void writeLazy(byte[] value, int offset, int length) throws IOException { + flush(); + out.writeLazy(value, offset, length); + totalBytesWritten += length; + } + + @Override + public void write(ByteBuffer value) throws IOException { + flush(); + int length = value.remaining(); + out.write(value); + totalBytesWritten += length; + } + + @Override + public void writeLazy(ByteBuffer value) throws IOException { + flush(); + int length = value.remaining(); + out.writeLazy(value); + totalBytesWritten += length; + } + + private void flushIfNotAvailable(int requiredSize) throws IOException { + if (limit - position < requiredSize) { + doFlush(); + } + } + + private void doFlush() throws IOException { + out.write(buffer, 0, position); + position = 0; + } + } + + /** + * An {@link CodedOutputStream} that decorates an {@link OutputStream}. It performs internal + * buffering to optimize writes to the {@link OutputStream}. + */ + private static final class OutputStreamEncoder extends AbstractBufferedEncoder { + private final OutputStream out; + + OutputStreamEncoder(OutputStream out, int bufferSize) { + super(bufferSize); + if (out == null) { + throw new NullPointerException("out"); + } + this.out = out; + } + + @Override + public void writeTag(final int fieldNumber, final int wireType) throws IOException { + writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType)); + } + + @Override + public void writeInt32(final int fieldNumber, final int value) throws IOException { + flushIfNotAvailable(MAX_VARINT_SIZE * 2); + bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + bufferInt32NoTag(value); + } + + @Override + public void writeUInt32(final int fieldNumber, final int value) throws IOException { + flushIfNotAvailable(MAX_VARINT_SIZE * 2); + bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + bufferUInt32NoTag(value); + } + + @Override + public void writeFixed32(final int fieldNumber, final int value) throws IOException { + flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_32_SIZE); + bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); + bufferFixed32NoTag(value); + } + + @Override + public void writeUInt64(final int fieldNumber, final long value) throws IOException { + flushIfNotAvailable(MAX_VARINT_SIZE * 2); + bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + bufferUInt64NoTag(value); + } + + @Override + public void writeFixed64(final int fieldNumber, final long value) throws IOException { + flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_64_SIZE); + bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); + bufferFixed64NoTag(value); + } + + @Override + public void writeBool(final int fieldNumber, final boolean value) throws IOException { + flushIfNotAvailable(MAX_VARINT_SIZE + 1); + bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + buffer((byte) (value ? 1 : 0)); + } + + @Override + public void writeString(final int fieldNumber, final String value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeStringNoTag(value); + } + + @Override + public void writeBytes(final int fieldNumber, final ByteString value) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeBytesNoTag(value); + } + + @Override + public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException { + writeByteArray(fieldNumber, value, 0, value.length); + } + + @Override + public void writeByteArray( + final int fieldNumber, final byte[] value, final int offset, final int length) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeByteArrayNoTag(value, offset, length); + } + + @Override + 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 writeBytesNoTag(final ByteString value) throws IOException { + writeUInt32NoTag(value.size()); + value.writeTo(this); + } + + @Override + public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException { + writeUInt32NoTag(length); + write(value, offset, length); + } + + @Override + public void writeRawBytes(final ByteBuffer value) throws IOException { + if (value.hasArray()) { + write(value.array(), value.arrayOffset(), value.capacity()); + } else { + ByteBuffer duplicated = value.duplicate(); + duplicated.clear(); + write(duplicated); + } + } + + @Override + public void writeMessage(final int fieldNumber, final MessageLite value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeMessageNoTag(value); + } + + @Override + public void writeMessageSetExtension(final int fieldNumber, final MessageLite value) + throws IOException { + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); + writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); + writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value); + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); + } + + @Override + public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value) + throws IOException { + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); + writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); + writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value); + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); + } + + @Override + public void writeMessageNoTag(final MessageLite value) throws IOException { + writeUInt32NoTag(value.getSerializedSize()); + value.writeTo(this); + } + + @Override + public void write(byte value) throws IOException { + if (position == limit) { + doFlush(); + } + + buffer(value); + } + + @Override + public void writeInt32NoTag(int value) throws IOException { + if (value >= 0) { + writeUInt32NoTag(value); + } else { + // Must sign-extend. + writeUInt64NoTag(value); + } + } + + @Override + public void writeUInt32NoTag(int value) throws IOException { + flushIfNotAvailable(MAX_VARINT_SIZE); + bufferUInt32NoTag(value); + } + + @Override + public void writeFixed32NoTag(final int value) throws IOException { + flushIfNotAvailable(FIXED_32_SIZE); + bufferFixed32NoTag(value); + } + + @Override + public void writeUInt64NoTag(long value) throws IOException { + flushIfNotAvailable(MAX_VARINT_SIZE); + bufferUInt64NoTag(value); + } + + @Override + public void writeFixed64NoTag(final long value) throws IOException { + flushIfNotAvailable(FIXED_64_SIZE); + bufferFixed64NoTag(value); + } + + @Override + public void writeStringNoTag(String value) throws IOException { + try { + // 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. We take advantage of this in both branches below. + final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR; + final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength); + + // If we are streaming and the potential length is too big to fit in our buffer, we take the + // slower path. + if (maxLengthVarIntSize + maxLength > limit) { + // Allocate a byte[] that we know can fit the string and encode into it. String.getBytes() + // does the same internally and then does *another copy* to return a byte[] of exactly the + // right size. We can skip that copy and just writeRawBytes up to the actualLength of the + // UTF-8 encoded bytes. + final byte[] encodedBytes = new byte[maxLength]; + int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength); + writeUInt32NoTag(actualLength); + writeLazy(encodedBytes, 0, actualLength); + return; + } + + // Fast path: we have enough space available in our buffer for the string... + if (maxLengthVarIntSize + maxLength > limit - position) { + // Flush to free up space. + doFlush(); + } + + // Optimize for the case where we know this length results in a constant varint length as + // this saves a pass for measuring the length of the string. + final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length()); + int oldPosition = position; + final int length; + try { + if (minLengthVarIntSize == maxLengthVarIntSize) { + position = oldPosition + minLengthVarIntSize; + int newPosition = Utf8.encode(value, buffer, position, limit - position); + // Since this class is stateful and tracks the position, we rewind and store the + // state, prepend the length, then reset it back to the end of the string. + position = oldPosition; + length = newPosition - oldPosition - minLengthVarIntSize; + bufferUInt32NoTag(length); + position = newPosition; + } else { + length = Utf8.encodedLength(value); + bufferUInt32NoTag(length); + position = Utf8.encode(value, buffer, position, length); + } + totalBytesWritten += length; + } catch (UnpairedSurrogateException e) { + // Be extra careful and restore the original position for retrying the write with the + // less efficient path. + totalBytesWritten -= position - oldPosition; + position = oldPosition; + throw e; + } catch (ArrayIndexOutOfBoundsException e) { + throw new OutOfSpaceException(e); + } + } catch (UnpairedSurrogateException e) { + inefficientWriteStringNoTag(value, e); + } + } + + @Override + public void flush() throws IOException { + if (position > 0) { + // Flush the buffer. + doFlush(); + } + } + + @Override + 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); + position += length; + totalBytesWritten += length; + } else { + // Write extends past current buffer. Fill the rest of this buffer and + // flush. + final int bytesWritten = limit - position; + System.arraycopy(value, offset, buffer, position, bytesWritten); + offset += bytesWritten; + length -= bytesWritten; + position = limit; + totalBytesWritten += bytesWritten; + doFlush(); + + // 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. + System.arraycopy(value, offset, buffer, 0, length); + position = length; + } else { + // Write is very big. Let's do it all at once. + out.write(value, offset, length); + } + totalBytesWritten += length; + } + } + + @Override + public void writeLazy(byte[] value, int offset, int length) throws IOException { + write(value, offset, length); + } + + @Override + public void write(ByteBuffer value) throws IOException { + int length = value.remaining(); + if (limit - position >= length) { + // We have room in the current buffer. + value.get(buffer, position, length); + position += length; + totalBytesWritten += length; + } else { + // Write extends past current buffer. Fill the rest of this buffer and + // flush. + final int bytesWritten = limit - position; + value.get(buffer, position, bytesWritten); + length -= bytesWritten; + position = limit; + totalBytesWritten += bytesWritten; + doFlush(); + + // Now deal with the rest. + // Since we have an output stream, this is our buffer + // and buffer offset == 0 + while (length > limit) { + // Copy data into the buffer before writing it to OutputStream. + value.get(buffer, 0, limit); + out.write(buffer, 0, limit); + length -= limit; + totalBytesWritten += limit; + } + value.get(buffer, 0, length); + position = length; + totalBytesWritten += length; + } + } + + @Override + public void writeLazy(ByteBuffer value) throws IOException { + write(value); + } + + private void flushIfNotAvailable(int requiredSize) throws IOException { + if (limit - position < requiredSize) { + doFlush(); + } + } + + private void doFlush() throws IOException { + out.write(buffer, 0, position); + position = 0; + } + } + + /** + * Gets the {@code sun.misc.Unsafe} instance, or {@code null} if not available on this + * platform. + */ + private static sun.misc.Unsafe getUnsafe() { + sun.misc.Unsafe unsafe = null; + try { + unsafe = AccessController.doPrivileged(new PrivilegedExceptionAction<sun.misc.Unsafe>() { + @Override + public sun.misc.Unsafe run() throws Exception { + Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class; + + for (Field f : k.getDeclaredFields()) { + f.setAccessible(true); + Object x = f.get(null); + if (k.isInstance(x)) { + return k.cast(x); + } + } + // The sun.misc.Unsafe field does not exist. + return null; + } + }); + } catch (Throwable e) { + // Catching Throwable here due to the fact that Google AppEngine raises NoClassDefFoundError + // for Unsafe. + } + + logger.log(Level.FINEST, "sun.misc.Unsafe: {}", + unsafe != null ? "available" : "unavailable"); + return unsafe; + } + + /** + * Indicates whether or not unsafe array operations are supported on this platform. + */ + // TODO(nathanmittler): Add support for Android's MemoryBlock. + private static boolean supportsUnsafeArrayOperations() { + boolean supported = false; + if (UNSAFE != null) { + try { + UNSAFE.getClass().getMethod("arrayBaseOffset", Class.class); + UNSAFE.getClass().getMethod("putByte", Object.class, long.class, byte.class); + supported = true; + } catch (Throwable e) { + // Do nothing. + } + } + logger.log(Level.FINEST, "Unsafe array operations: {}", + supported ? "available" : "unavailable"); + return supported; + } + + /** + * Get the base offset for byte arrays, or {@code -1} if {@code sun.misc.Unsafe} is not + * available. + */ + private static <T> int byteArrayBaseOffset() { + return HAS_UNSAFE_ARRAY_OPERATIONS ? UNSAFE.arrayBaseOffset(byte[].class) : -1; } } 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 e303e138..e00ea342 100644 --- a/java/core/src/main/java/com/google/protobuf/Descriptors.java +++ b/java/core/src/main/java/com/google/protobuf/Descriptors.java @@ -74,16 +74,28 @@ public final class Descriptors { */ public static final class FileDescriptor extends GenericDescriptor { /** Convert the descriptor to its protocol message representation. */ - public FileDescriptorProto toProto() { return proto; } + @Override + public FileDescriptorProto toProto() { + return proto; + } /** Get the file name. */ - public String getName() { return proto.getName(); } + @Override + public String getName() { + return proto.getName(); + } /** Returns this object. */ - public FileDescriptor getFile() { return this; } + @Override + public FileDescriptor getFile() { + return this; + } /** Returns the same as getName(). */ - public String getFullName() { return proto.getName(); } + @Override + public String getFullName() { + return proto.getName(); + } /** * Get the proto package name. This is the package name given by the @@ -582,10 +594,16 @@ public final class Descriptors { public int getIndex() { return index; } /** Convert the descriptor to its protocol message representation. */ - public DescriptorProto toProto() { return proto; } + @Override + public DescriptorProto toProto() { + return proto; + } /** Get the type's unqualified name. */ - public String getName() { return proto.getName(); } + @Override + public String getName() { + return proto.getName(); + } /** * Get the type's fully-qualified name, within the proto language's @@ -598,10 +616,16 @@ public final class Descriptors { * </pre> * {@code Baz}'s full name is "foo.bar.Baz". */ - public String getFullName() { return fullName; } + @Override + public String getFullName() { + return fullName; + } /** Get the {@link FileDescriptor} containing this descriptor. */ - public FileDescriptor getFile() { return file; } + @Override + public FileDescriptor getFile() { + return file; + } /** If this is a nested type, get the outer descriptor, otherwise null. */ public Descriptor getContainingType() { return containingType; } @@ -875,19 +899,31 @@ public final class Descriptors { public int getIndex() { return index; } /** Convert the descriptor to its protocol message representation. */ - public FieldDescriptorProto toProto() { return proto; } + @Override + public FieldDescriptorProto toProto() { + return proto; + } /** Get the field's unqualified name. */ - public String getName() { return proto.getName(); } + @Override + public String getName() { + return proto.getName(); + } /** Get the field's number. */ - public int getNumber() { return proto.getNumber(); } + @Override + public int getNumber() { + return proto.getNumber(); + } /** * Get the field's fully-qualified name. * @see Descriptors.Descriptor#getFullName() */ - public String getFullName() { return fullName; } + @Override + public String getFullName() { + return fullName; + } /** Get the JSON name of this field. */ public String getJsonName() { @@ -901,17 +937,22 @@ public final class Descriptors { public JavaType getJavaType() { return type.getJavaType(); } /** For internal use only. */ + @Override public WireFormat.JavaType getLiteJavaType() { return getLiteType().getJavaType(); } /** Get the {@code FileDescriptor} containing this descriptor. */ - public FileDescriptor getFile() { return file; } + @Override + public FileDescriptor getFile() { + return file; + } /** Get the field's declared type. */ public Type getType() { return type; } /** For internal use only. */ + @Override public WireFormat.FieldType getLiteType() { return table[type.ordinal()]; } @@ -953,6 +994,7 @@ public final class Descriptors { } /** Is this field declared repeated? */ + @Override public boolean isRepeated() { return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REPEATED; } @@ -960,6 +1002,7 @@ public final class Descriptors { /** Does this field have the {@code [packed = true]} option or is this field * packable in proto3 and not explicitly setted to unpacked? */ + @Override public boolean isPacked() { if (!isPackable()) { return false; @@ -1048,6 +1091,7 @@ public final class Descriptors { } /** For enum fields, gets the field's type. */ + @Override public EnumDescriptor getEnumType() { if (getJavaType() != JavaType.ENUM) { throw new UnsupportedOperationException( @@ -1066,6 +1110,7 @@ public final class Descriptors { * @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( @@ -1466,8 +1511,8 @@ public final class Descriptors { * For internal use only. This is to satisfy the FieldDescriptorLite * interface. */ - public MessageLite.Builder internalMergeFrom( - MessageLite.Builder to, MessageLite from) { + @Override + public MessageLite.Builder internalMergeFrom(MessageLite.Builder to, MessageLite from) { // FieldDescriptors are only used with non-lite messages so we can just // down-cast and call mergeFrom directly. return ((Message.Builder) to).mergeFrom((Message) from); @@ -1487,19 +1532,31 @@ public final class Descriptors { public int getIndex() { return index; } /** Convert the descriptor to its protocol message representation. */ - public EnumDescriptorProto toProto() { return proto; } + @Override + public EnumDescriptorProto toProto() { + return proto; + } /** Get the type's unqualified name. */ - public String getName() { return proto.getName(); } + @Override + public String getName() { + return proto.getName(); + } /** * Get the type's fully-qualified name. * @see Descriptors.Descriptor#getFullName() */ - public String getFullName() { return fullName; } + @Override + public String getFullName() { + return fullName; + } /** Get the {@link FileDescriptor} containing this descriptor. */ - public FileDescriptor getFile() { return file; } + @Override + public FileDescriptor getFile() { + return file; + } /** If this is a nested type, get the outer descriptor, otherwise null. */ public Descriptor getContainingType() { return containingType; } @@ -1533,6 +1590,7 @@ public final class Descriptors { * @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)); @@ -1659,13 +1717,22 @@ public final class Descriptors { public int getIndex() { return index; } /** Convert the descriptor to its protocol message representation. */ - public EnumValueDescriptorProto toProto() { return proto; } + @Override + public EnumValueDescriptorProto toProto() { + return proto; + } /** Get the value's unqualified name. */ - public String getName() { return proto.getName(); } + @Override + public String getName() { + return proto.getName(); + } /** Get the value's number. */ - public int getNumber() { return proto.getNumber(); } + @Override + public int getNumber() { + return proto.getNumber(); + } @Override public String toString() { return proto.getName(); } @@ -1674,10 +1741,16 @@ public final class Descriptors { * Get the value's fully-qualified name. * @see Descriptors.Descriptor#getFullName() */ - public String getFullName() { return fullName; } + @Override + public String getFullName() { + return fullName; + } /** Get the {@link FileDescriptor} containing this descriptor. */ - public FileDescriptor getFile() { return file; } + @Override + public FileDescriptor getFile() { + return file; + } /** Get the value's enum type. */ public EnumDescriptor getType() { return type; } @@ -1745,19 +1818,31 @@ public final class Descriptors { public int getIndex() { return index; } /** Convert the descriptor to its protocol message representation. */ - public ServiceDescriptorProto toProto() { return proto; } + @Override + public ServiceDescriptorProto toProto() { + return proto; + } /** Get the type's unqualified name. */ - public String getName() { return proto.getName(); } + @Override + public String getName() { + return proto.getName(); + } /** * Get the type's fully-qualified name. * @see Descriptors.Descriptor#getFullName() */ - public String getFullName() { return fullName; } + @Override + public String getFullName() { + return fullName; + } /** Get the {@link FileDescriptor} containing this descriptor. */ - public FileDescriptor getFile() { return file; } + @Override + public FileDescriptor getFile() { + return file; + } /** Get the {@code ServiceOptions}, defined in {@code descriptor.proto}. */ public ServiceOptions getOptions() { return proto.getOptions(); } @@ -1835,19 +1920,31 @@ public final class Descriptors { public int getIndex() { return index; } /** Convert the descriptor to its protocol message representation. */ - public MethodDescriptorProto toProto() { return proto; } + @Override + public MethodDescriptorProto toProto() { + return proto; + } /** Get the method's unqualified name. */ - public String getName() { return proto.getName(); } + @Override + public String getName() { + return proto.getName(); + } /** * Get the method's fully-qualified name. * @see Descriptors.Descriptor#getFullName() */ - public String getFullName() { return fullName; } + @Override + public String getFullName() { + return fullName; + } /** Get the {@link FileDescriptor} containing this descriptor. */ - public FileDescriptor getFile() { return file; } + @Override + public FileDescriptor getFile() { + return file; + } /** Get the method's service type. */ public ServiceDescriptor getService() { return service; } @@ -2248,10 +2345,22 @@ public final class Descriptors { * that has the same name as an existing package. */ private static final class PackageDescriptor extends GenericDescriptor { - public Message toProto() { return file.toProto(); } - public String getName() { return name; } - public String getFullName() { return fullName; } - public FileDescriptor getFile() { return file; } + @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) { 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 bcc9d6ee..a9543b83 100644 --- a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java @@ -34,7 +34,6 @@ import com.google.protobuf.Internal.DoubleList; import java.util.Arrays; import java.util.Collection; -import java.util.List; import java.util.RandomAccess; /** @@ -45,8 +44,6 @@ import java.util.RandomAccess; final class DoubleArrayList extends AbstractProtobufList<Double> implements DoubleList, RandomAccess { - private static final int DEFAULT_CAPACITY = 10; - private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList(); static { EMPTY_LIST.makeImmutable(); @@ -71,32 +68,56 @@ final class DoubleArrayList * Constructs a new mutable {@code DoubleArrayList} with default capacity. */ DoubleArrayList() { - this(DEFAULT_CAPACITY); - } - - /** - * Constructs a new mutable {@code DoubleArrayList} with the provided capacity. - */ - DoubleArrayList(int capacity) { - array = new double[capacity]; - size = 0; + this(new double[DEFAULT_CAPACITY], 0); } /** * Constructs a new mutable {@code DoubleArrayList} containing the same elements as {@code other}. */ - DoubleArrayList(List<Double> other) { - if (other instanceof DoubleArrayList) { - DoubleArrayList list = (DoubleArrayList) other; - array = list.array.clone(); - size = list.size; - } else { - size = other.size(); - array = new double[size]; - for (int i = 0; i < size; i++) { - array[i] = other.get(i); + private DoubleArrayList(double[] array, int size) { + this.array = array; + this.size = size; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof DoubleArrayList)) { + return super.equals(o); + } + DoubleArrayList other = (DoubleArrayList) o; + if (size != other.size) { + return false; + } + + final double[] arr = other.array; + for (int i = 0; i < size; i++) { + if (array[i] != arr[i]) { + return false; } } + + return true; + } + + @Override + public int hashCode() { + int result = 1; + for (int i = 0; i < size; i++) { + long bits = Double.doubleToLongBits(array[i]); + result = (31 * result) + Internal.hashLong(bits); + } + return result; + } + + @Override + public DoubleList mutableCopyWithCapacity(int capacity) { + if (capacity < size) { + throw new IllegalArgumentException(); + } + return new DoubleArrayList(Arrays.copyOf(array, capacity), size); } @Override 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 3ea1b688..859a9e8f 100644 --- a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java +++ b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java @@ -156,18 +156,22 @@ public final class DynamicMessage extends AbstractMessage { // ----------------------------------------------------------------- // Implementation of Message interface. + @Override public Descriptor getDescriptorForType() { return type; } + @Override public DynamicMessage getDefaultInstanceForType() { return getDefaultInstance(type); } + @Override public Map<FieldDescriptor, Object> getAllFields() { return fields.getAllFields(); } + @Override public boolean hasOneof(OneofDescriptor oneof) { verifyOneofContainingType(oneof); FieldDescriptor field = oneofCases[oneof.getIndex()]; @@ -177,16 +181,19 @@ public final class DynamicMessage extends AbstractMessage { return true; } + @Override public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) { verifyOneofContainingType(oneof); return oneofCases[oneof.getIndex()]; } + @Override public boolean hasField(FieldDescriptor field) { verifyContainingType(field); return fields.hasField(field); } + @Override public Object getField(FieldDescriptor field) { verifyContainingType(field); Object result = fields.getField(field); @@ -202,16 +209,19 @@ public final class DynamicMessage extends AbstractMessage { return result; } + @Override public int getRepeatedFieldCount(FieldDescriptor field) { verifyContainingType(field); return fields.getRepeatedFieldCount(field); } + @Override public Object getRepeatedField(FieldDescriptor field, int index) { verifyContainingType(field); return fields.getRepeatedField(field, index); } + @Override public UnknownFieldSet getUnknownFields() { return unknownFields; } @@ -264,19 +274,22 @@ public final class DynamicMessage extends AbstractMessage { return size; } + @Override public Builder newBuilderForType() { return new Builder(type); } + @Override public Builder toBuilder() { return newBuilderForType().mergeFrom(this); } + @Override public Parser<DynamicMessage> getParserForType() { return new AbstractParser<DynamicMessage>() { + @Override public DynamicMessage parsePartialFrom( - CodedInputStream input, - ExtensionRegistryLite extensionRegistry) + CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { Builder builder = newBuilder(type); try { @@ -370,6 +383,7 @@ public final class DynamicMessage extends AbstractMessage { } } + @Override public DynamicMessage build() { if (!isInitialized()) { throw newUninitializedMessageException( @@ -394,6 +408,7 @@ public final class DynamicMessage extends AbstractMessage { return buildPartial(); } + @Override public DynamicMessage buildPartial() { fields.makeImmutable(); DynamicMessage result = @@ -411,22 +426,27 @@ public final class DynamicMessage extends AbstractMessage { return result; } + @Override public boolean isInitialized() { return DynamicMessage.isInitialized(type, fields); } + @Override public Descriptor getDescriptorForType() { return type; } + @Override public DynamicMessage getDefaultInstanceForType() { return getDefaultInstance(type); } + @Override public Map<FieldDescriptor, Object> getAllFields() { return fields.getAllFields(); } + @Override public Builder newBuilderForField(FieldDescriptor field) { verifyContainingType(field); @@ -438,6 +458,7 @@ public final class DynamicMessage extends AbstractMessage { return new Builder(field.getMessageType()); } + @Override public boolean hasOneof(OneofDescriptor oneof) { verifyOneofContainingType(oneof); FieldDescriptor field = oneofCases[oneof.getIndex()]; @@ -447,11 +468,13 @@ public final class DynamicMessage extends AbstractMessage { return true; } + @Override public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) { verifyOneofContainingType(oneof); return oneofCases[oneof.getIndex()]; } + @Override public Builder clearOneof(OneofDescriptor oneof) { verifyOneofContainingType(oneof); FieldDescriptor field = oneofCases[oneof.getIndex()]; @@ -461,11 +484,13 @@ public final class DynamicMessage extends AbstractMessage { return this; } + @Override public boolean hasField(FieldDescriptor field) { verifyContainingType(field); return fields.hasField(field); } + @Override public Object getField(FieldDescriptor field) { verifyContainingType(field); Object result = fields.getField(field); @@ -481,6 +506,7 @@ public final class DynamicMessage extends AbstractMessage { return result; } + @Override public Builder setField(FieldDescriptor field, Object value) { verifyContainingType(field); ensureIsMutable(); @@ -505,6 +531,7 @@ public final class DynamicMessage extends AbstractMessage { return this; } + @Override public Builder clearField(FieldDescriptor field) { verifyContainingType(field); ensureIsMutable(); @@ -519,24 +546,27 @@ public final class DynamicMessage extends AbstractMessage { return this; } + @Override public int getRepeatedFieldCount(FieldDescriptor field) { verifyContainingType(field); return fields.getRepeatedFieldCount(field); } + @Override public Object getRepeatedField(FieldDescriptor field, int index) { verifyContainingType(field); return fields.getRepeatedField(field, index); } - public Builder setRepeatedField(FieldDescriptor field, - int index, Object value) { + @Override + public Builder setRepeatedField(FieldDescriptor field, int index, Object value) { verifyContainingType(field); ensureIsMutable(); fields.setRepeatedField(field, index, value); return this; } + @Override public Builder addRepeatedField(FieldDescriptor field, Object value) { verifyContainingType(field); ensureIsMutable(); @@ -544,10 +574,12 @@ public final class DynamicMessage extends AbstractMessage { return this; } + @Override public UnknownFieldSet getUnknownFields() { return unknownFields; } + @Override public Builder setUnknownFields(UnknownFieldSet unknownFields) { if (getDescriptorForType().getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3) { 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 68d29f33..08ec5b45 100644 --- a/java/core/src/main/java/com/google/protobuf/Extension.java +++ b/java/core/src/main/java/com/google/protobuf/Extension.java @@ -42,6 +42,7 @@ public abstract class Extension<ContainingType extends MessageLite, Type> public abstract Descriptors.FieldDescriptor getDescriptor(); /** Returns whether or not this extension is a Lite Extension. */ + @Override final boolean isLite() { return false; } 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 47924b65..4e89709f 100644 --- a/java/core/src/main/java/com/google/protobuf/FieldSet.java +++ b/java/core/src/main/java/com/google/protobuf/FieldSet.java @@ -120,6 +120,25 @@ final class FieldSet<FieldDescriptorType extends public boolean isImmutable() { return isImmutable; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (!(o instanceof FieldSet)) { + return false; + } + + FieldSet<?> other = (FieldSet<?>) o; + return other.fields.equals(other.fields); + } + + @Override + public int hashCode() { + return fields.hashCode(); + } /** * Clones the FieldSet. The returned FieldSet will be mutable even if the 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 033b5eed..63cb6d77 100644 --- a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java @@ -34,7 +34,6 @@ import com.google.protobuf.Internal.FloatList; import java.util.Arrays; import java.util.Collection; -import java.util.List; import java.util.RandomAccess; /** @@ -44,8 +43,6 @@ import java.util.RandomAccess; */ final class FloatArrayList extends AbstractProtobufList<Float> implements FloatList, RandomAccess { - private static final int DEFAULT_CAPACITY = 10; - private static final FloatArrayList EMPTY_LIST = new FloatArrayList(); static { EMPTY_LIST.makeImmutable(); @@ -70,32 +67,55 @@ final class FloatArrayList extends AbstractProtobufList<Float> implements FloatL * Constructs a new mutable {@code FloatArrayList} with default capacity. */ FloatArrayList() { - this(DEFAULT_CAPACITY); - } - - /** - * Constructs a new mutable {@code FloatArrayList} with the provided capacity. - */ - FloatArrayList(int capacity) { - array = new float[capacity]; - size = 0; + this(new float[DEFAULT_CAPACITY], 0); } /** * Constructs a new mutable {@code FloatArrayList} containing the same elements as {@code other}. */ - FloatArrayList(List<Float> other) { - if (other instanceof FloatArrayList) { - FloatArrayList list = (FloatArrayList) other; - array = list.array.clone(); - size = list.size; - } else { - size = other.size(); - array = new float[size]; - for (int i = 0; i < size; i++) { - array[i] = other.get(i); + private FloatArrayList(float[] array, int size) { + this.array = array; + this.size = size; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof FloatArrayList)) { + return super.equals(o); + } + FloatArrayList other = (FloatArrayList) o; + if (size != other.size) { + return false; + } + + final float[] arr = other.array; + for (int i = 0; i < size; i++) { + if (array[i] != arr[i]) { + return false; } } + + return true; + } + + @Override + public int hashCode() { + int result = 1; + for (int i = 0; i < size; i++) { + result = (31 * result) + Float.floatToIntBits(array[i]); + } + return result; + } + + @Override + public FloatList mutableCopyWithCapacity(int capacity) { + if (capacity < size) { + throw new IllegalArgumentException(); + } + return new FloatArrayList(Arrays.copyOf(array, capacity), size); } @Override 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 a50afe55..790cb622 100644 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java @@ -80,6 +80,7 @@ public abstract class GeneratedMessage extends AbstractMessage unknownFields = builder.getUnknownFields(); } + @Override public Parser<? extends GeneratedMessage> getParserForType() { throw new UnsupportedOperationException( "This is supposed to be overridden by subclasses."); @@ -102,7 +103,7 @@ public abstract class GeneratedMessage extends AbstractMessage */ protected abstract FieldAccessorTable internalGetFieldAccessorTable(); - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public Descriptor getDescriptorForType() { return internalGetFieldAccessorTable().descriptor; } @@ -191,7 +192,7 @@ public abstract class GeneratedMessage extends AbstractMessage return true; } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public Map<FieldDescriptor, Object> getAllFields() { return Collections.unmodifiableMap( getAllFieldsMutable(/* getBytesForString = */ false)); @@ -212,22 +213,22 @@ public abstract class GeneratedMessage extends AbstractMessage getAllFieldsMutable(/* getBytesForString = */ true)); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public boolean hasOneof(final OneofDescriptor oneof) { return internalGetFieldAccessorTable().getOneof(oneof).has(this); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) { return internalGetFieldAccessorTable().getOneof(oneof).get(this); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public boolean hasField(final FieldDescriptor field) { return internalGetFieldAccessorTable().getField(field).has(this); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public Object getField(final FieldDescriptor field) { return internalGetFieldAccessorTable().getField(field).get(this); } @@ -244,19 +245,19 @@ public abstract class GeneratedMessage extends AbstractMessage return internalGetFieldAccessorTable().getField(field).getRaw(this); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public int getRepeatedFieldCount(final FieldDescriptor field) { return internalGetFieldAccessorTable().getField(field) .getRepeatedCount(this); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public Object getRepeatedField(final FieldDescriptor field, final int index) { return internalGetFieldAccessorTable().getField(field) .getRepeated(this, index); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public UnknownFieldSet getUnknownFields() { throw new UnsupportedOperationException( "This is supposed to be overridden by subclasses."); @@ -380,7 +381,7 @@ public abstract class GeneratedMessage extends AbstractMessage } @SuppressWarnings("unchecked") - public abstract static class Builder <BuilderType extends Builder> + public abstract static class Builder <BuilderType extends Builder<BuilderType>> extends AbstractMessage.Builder<BuilderType> { private BuilderParent builderParent; @@ -444,6 +445,7 @@ public abstract class GeneratedMessage extends AbstractMessage * Called by the initialization and clear code paths to allow subclasses to * reset any of their builtin fields back to the initial values. */ + @Override public BuilderType clear() { unknownFields = UnknownFieldSet.getDefaultInstance(); onChanged(); @@ -457,12 +459,12 @@ public abstract class GeneratedMessage extends AbstractMessage */ protected abstract FieldAccessorTable internalGetFieldAccessorTable(); - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public Descriptor getDescriptorForType() { return internalGetFieldAccessorTable().descriptor; } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public Map<FieldDescriptor, Object> getAllFields() { return Collections.unmodifiableMap(getAllFieldsMutable()); } @@ -510,39 +512,38 @@ public abstract class GeneratedMessage extends AbstractMessage return result; } - public Message.Builder newBuilderForField( - final FieldDescriptor field) { + @Override + public Message.Builder newBuilderForField(final FieldDescriptor field) { return internalGetFieldAccessorTable().getField(field).newBuilder(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public Message.Builder getFieldBuilder(final FieldDescriptor field) { return internalGetFieldAccessorTable().getField(field).getBuilder(this); } - //@Override (Java 1.6 override semantics, but we must support 1.5) - public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, - int index) { + @Override + public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) { return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder( this, index); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public boolean hasOneof(final OneofDescriptor oneof) { return internalGetFieldAccessorTable().getOneof(oneof).has(this); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) { return internalGetFieldAccessorTable().getOneof(oneof).get(this); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public boolean hasField(final FieldDescriptor field) { return internalGetFieldAccessorTable().getField(field).has(this); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public Object getField(final FieldDescriptor field) { Object object = internalGetFieldAccessorTable().getField(field).get(this); if (field.isRepeated()) { @@ -554,52 +555,52 @@ public abstract class GeneratedMessage extends AbstractMessage } } - public BuilderType setField(final FieldDescriptor field, - final Object value) { + @Override + public BuilderType setField(final FieldDescriptor field, final Object value) { internalGetFieldAccessorTable().getField(field).set(this, value); return (BuilderType) this; } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public BuilderType clearField(final FieldDescriptor field) { internalGetFieldAccessorTable().getField(field).clear(this); return (BuilderType) this; } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public BuilderType clearOneof(final OneofDescriptor oneof) { internalGetFieldAccessorTable().getOneof(oneof).clear(this); return (BuilderType) this; } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public int getRepeatedFieldCount(final FieldDescriptor field) { return internalGetFieldAccessorTable().getField(field) .getRepeatedCount(this); } - //@Override (Java 1.6 override semantics, but we must support 1.5) - public Object getRepeatedField(final FieldDescriptor field, - final int index) { + @Override + public Object getRepeatedField(final FieldDescriptor field, final int index) { return internalGetFieldAccessorTable().getField(field) .getRepeated(this, index); } - public BuilderType setRepeatedField(final FieldDescriptor field, - final int index, final Object value) { + @Override + public BuilderType setRepeatedField( + final FieldDescriptor field, final int index, final Object value) { internalGetFieldAccessorTable().getField(field) .setRepeated(this, index, value); return (BuilderType) this; } - public BuilderType addRepeatedField(final FieldDescriptor field, - final Object value) { + @Override + public BuilderType addRepeatedField(final FieldDescriptor field, final Object value) { internalGetFieldAccessorTable().getField(field).addRepeated(this, value); return (BuilderType) this; } - public BuilderType setUnknownFields( - final UnknownFieldSet unknownFields) { + @Override + public BuilderType setUnknownFields(final UnknownFieldSet unknownFields) { this.unknownFields = unknownFields; onChanged(); return (BuilderType) this; @@ -616,7 +617,7 @@ public abstract class GeneratedMessage extends AbstractMessage return (BuilderType) this; } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public boolean isInitialized() { for (final FieldDescriptor field : getDescriptorForType().getFields()) { // Check that all required fields are present. @@ -646,7 +647,7 @@ public abstract class GeneratedMessage extends AbstractMessage return true; } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public final UnknownFieldSet getUnknownFields() { return unknownFields; } @@ -670,7 +671,7 @@ public abstract class GeneratedMessage extends AbstractMessage */ private class BuilderParentImpl implements BuilderParent { - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public void markDirty() { onChanged(); } @@ -735,6 +736,7 @@ public abstract class GeneratedMessage extends AbstractMessage public interface ExtendableMessageOrBuilder< MessageType extends ExtendableMessage> extends MessageOrBuilder { // Re-define for return type covariance. + @Override Message getDefaultInstanceForType(); /** Check if a singular extension is present. */ @@ -795,6 +797,8 @@ public abstract class GeneratedMessage extends AbstractMessage extends GeneratedMessage implements ExtendableMessageOrBuilder<MessageType> { + private static final long serialVersionUID = 1L; + private final FieldSet<FieldDescriptor> extensions; protected ExtendableMessage() { @@ -821,9 +825,8 @@ public abstract class GeneratedMessage extends AbstractMessage } /** Check if a singular extension is present. */ - //@Override (Java 1.6 override semantics, but we must support 1.5) - public final <Type> boolean hasExtension( - final ExtensionLite<MessageType, Type> extensionLite) { + @Override + public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) { Extension<MessageType, Type> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -831,7 +834,7 @@ public abstract class GeneratedMessage extends AbstractMessage } /** Get the number of elements in a repeated extension. */ - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public final <Type> int getExtensionCount( final ExtensionLite<MessageType, List<Type>> extensionLite) { Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite); @@ -842,10 +845,9 @@ public abstract class GeneratedMessage extends AbstractMessage } /** Get the value of an extension. */ - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override @SuppressWarnings("unchecked") - public final <Type> Type getExtension( - final ExtensionLite<MessageType, Type> extensionLite) { + public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) { Extension<MessageType, Type> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -867,11 +869,10 @@ public abstract class GeneratedMessage extends AbstractMessage } /** Get one element of a repeated extension. */ - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override @SuppressWarnings("unchecked") public final <Type> Type getExtension( - final ExtensionLite<MessageType, List<Type>> extensionLite, - final int index) { + final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) { Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -1105,7 +1106,7 @@ public abstract class GeneratedMessage extends AbstractMessage @SuppressWarnings("unchecked") public abstract static class ExtendableBuilder< MessageType extends ExtendableMessage, - BuilderType extends ExtendableBuilder> + BuilderType extends ExtendableBuilder<MessageType, BuilderType>> extends Builder<BuilderType> implements ExtendableMessageOrBuilder<MessageType> { @@ -1157,9 +1158,8 @@ public abstract class GeneratedMessage extends AbstractMessage } /** Check if a singular extension is present. */ - //@Override (Java 1.6 override semantics, but we must support 1.5) - public final <Type> boolean hasExtension( - final ExtensionLite<MessageType, Type> extensionLite) { + @Override + public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) { Extension<MessageType, Type> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -1167,7 +1167,7 @@ public abstract class GeneratedMessage extends AbstractMessage } /** Get the number of elements in a repeated extension. */ - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public final <Type> int getExtensionCount( final ExtensionLite<MessageType, List<Type>> extensionLite) { Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite); @@ -1178,9 +1178,8 @@ public abstract class GeneratedMessage extends AbstractMessage } /** Get the value of an extension. */ - //@Override (Java 1.6 override semantics, but we must support 1.5) - public final <Type> Type getExtension( - final ExtensionLite<MessageType, Type> extensionLite) { + @Override + public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) { Extension<MessageType, Type> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -1202,10 +1201,9 @@ public abstract class GeneratedMessage extends AbstractMessage } /** Get one element of a repeated extension. */ - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public final <Type> Type getExtension( - final ExtensionLite<MessageType, List<Type>> extensionLite, - final int index) { + final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) { Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -1458,10 +1456,9 @@ public abstract class GeneratedMessage extends AbstractMessage // obtained. return new GeneratedExtension<ContainingType, Type>( new CachedDescriptorRetriever() { - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public FieldDescriptor loadDescriptor() { - return scope.getDescriptorForType().getExtensions() - .get(descriptorIndex); + return scope.getDescriptorForType().getExtensions().get(descriptorIndex); } }, singularType, @@ -1489,6 +1486,7 @@ public abstract class GeneratedMessage extends AbstractMessage private volatile FieldDescriptor descriptor; protected abstract FieldDescriptor loadDescriptor(); + @Override public FieldDescriptor getDescriptor() { if (descriptor == null) { synchronized (this) { @@ -1518,6 +1516,7 @@ public abstract class GeneratedMessage extends AbstractMessage // obtained. return new GeneratedExtension<ContainingType, Type>( new CachedDescriptorRetriever() { + @Override protected FieldDescriptor loadDescriptor() { return scope.getDescriptorForType().findFieldByName(name); } @@ -1544,17 +1543,18 @@ public abstract class GeneratedMessage extends AbstractMessage // used to obtain the extension's FieldDescriptor. return new GeneratedExtension<ContainingType, Type>( new CachedDescriptorRetriever() { + @Override protected FieldDescriptor loadDescriptor() { try { - Class clazz = - singularType.getClassLoader().loadClass(descriptorOuterClass); - FileDescriptor file = - (FileDescriptor) clazz.getField("descriptor").get(null); + Class clazz = singularType.getClassLoader().loadClass(descriptorOuterClass); + FileDescriptor file = (FileDescriptor) clazz.getField("descriptor").get(null); return file.findExtensionByName(extensionName); } catch (Exception e) { throw new RuntimeException( - "Cannot load descriptors: " + descriptorOuterClass + - " is not a valid descriptor class name", e); + "Cannot load descriptors: " + + descriptorOuterClass + + " is not a valid descriptor class name", + e); } } }, @@ -1636,12 +1636,13 @@ public abstract class GeneratedMessage extends AbstractMessage if (descriptorRetriever != null) { throw new IllegalStateException("Already initialized."); } - descriptorRetriever = new ExtensionDescriptorRetriever() { - //@Override (Java 1.6 override semantics, but we must support 1.5) - public FieldDescriptor getDescriptor() { - return descriptor; - } - }; + descriptorRetriever = + new ExtensionDescriptorRetriever() { + @Override + public FieldDescriptor getDescriptor() { + return descriptor; + } + }; } private ExtensionDescriptorRetriever descriptorRetriever; @@ -1651,6 +1652,7 @@ public abstract class GeneratedMessage extends AbstractMessage private final Method enumGetValueDescriptor; private final ExtensionType extensionType; + @Override public FieldDescriptor getDescriptor() { if (descriptorRetriever == null) { throw new IllegalStateException( @@ -1663,10 +1665,12 @@ public abstract class GeneratedMessage extends AbstractMessage * If the extension is an embedded message or group, returns the default * instance of the message. */ + @Override public Message getMessageDefaultInstance() { return messageDefaultInstance; } + @Override protected ExtensionType getExtensionType() { return extensionType; } @@ -1677,7 +1681,7 @@ public abstract class GeneratedMessage extends AbstractMessage * EnumValueDescriptors but the native accessors use the generated enum * type. */ - // @Override + @Override @SuppressWarnings("unchecked") protected Object fromReflectionType(final Object value) { FieldDescriptor descriptor = getDescriptor(); @@ -1702,7 +1706,7 @@ public abstract class GeneratedMessage extends AbstractMessage * Like {@link #fromReflectionType(Object)}, but if the type is a repeated * type, this converts a single element. */ - // @Override + @Override protected Object singularFromReflectionType(final Object value) { FieldDescriptor descriptor = getDescriptor(); switch (descriptor.getJavaType()) { @@ -1726,7 +1730,7 @@ public abstract class GeneratedMessage extends AbstractMessage * EnumValueDescriptors but the native accessors use the generated enum * type. */ - // @Override + @Override @SuppressWarnings("unchecked") protected Object toReflectionType(final Object value) { FieldDescriptor descriptor = getDescriptor(); @@ -1750,7 +1754,7 @@ public abstract class GeneratedMessage extends AbstractMessage * Like {@link #toReflectionType(Object)}, but if the type is a repeated * type, this converts a single element. */ - // @Override + @Override protected Object singularToReflectionType(final Object value) { FieldDescriptor descriptor = getDescriptor(); switch (descriptor.getJavaType()) { @@ -1761,22 +1765,22 @@ public abstract class GeneratedMessage extends AbstractMessage } } - // @Override + @Override public int getNumber() { return getDescriptor().getNumber(); } - // @Override + @Override public WireFormat.FieldType getLiteType() { return getDescriptor().getLiteType(); } - // @Override + @Override public boolean isRepeated() { return getDescriptor().isRepeated(); } - // @Override + @Override @SuppressWarnings("unchecked") public Type getDefaultValue() { if (isRepeated()) { @@ -2126,49 +2130,57 @@ public abstract class GeneratedMessage extends AbstractMessage return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); } + @Override public Object get(final GeneratedMessage message) { return invokeOrDie(getMethod, message); } + @Override public Object get(GeneratedMessage.Builder builder) { return invokeOrDie(getMethodBuilder, builder); } + @Override public Object getRaw(final GeneratedMessage message) { return get(message); } + @Override public Object getRaw(GeneratedMessage.Builder builder) { return get(builder); } + @Override public void set(final Builder builder, final Object value) { invokeOrDie(setMethod, builder, value); } - public Object getRepeated(final GeneratedMessage message, - final int index) { + @Override + public Object getRepeated(final GeneratedMessage message, final int index) { throw new UnsupportedOperationException( "getRepeatedField() called on a singular field."); } - public Object getRepeatedRaw(final GeneratedMessage message, - final int index) { + @Override + public Object getRepeatedRaw(final GeneratedMessage message, final int index) { throw new UnsupportedOperationException( "getRepeatedFieldRaw() called on a singular field."); } + @Override public Object getRepeated(GeneratedMessage.Builder builder, int index) { throw new UnsupportedOperationException( "getRepeatedField() called on a singular field."); } - public Object getRepeatedRaw(GeneratedMessage.Builder builder, - int index) { + @Override + public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) { throw new UnsupportedOperationException( "getRepeatedFieldRaw() called on a singular field."); } - public void setRepeated(final Builder builder, final int index, - final Object value) { + @Override + public void setRepeated(final Builder builder, final int index, final Object value) { 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."); } + @Override public boolean has(final GeneratedMessage message) { if (!hasHasMethod) { if (isOneofField) { @@ -2178,6 +2190,7 @@ public abstract class GeneratedMessage extends AbstractMessage } return (Boolean) invokeOrDie(hasMethod, message); } + @Override public boolean has(GeneratedMessage.Builder builder) { if (!hasHasMethod) { if (isOneofField) { @@ -2187,27 +2200,32 @@ public abstract class GeneratedMessage extends AbstractMessage } return (Boolean) invokeOrDie(hasMethodBuilder, builder); } + @Override public int getRepeatedCount(final GeneratedMessage message) { throw new UnsupportedOperationException( "getRepeatedFieldSize() called on a singular field."); } + @Override public int getRepeatedCount(GeneratedMessage.Builder builder) { throw new UnsupportedOperationException( "getRepeatedFieldSize() called on a singular field."); } + @Override public void clear(final Builder builder) { invokeOrDie(clearMethod, builder); } + @Override public Message.Builder newBuilder() { throw new UnsupportedOperationException( "newBuilderForField() called on a non-Message type."); } + @Override public Message.Builder getBuilder(GeneratedMessage.Builder builder) { throw new UnsupportedOperationException( "getFieldBuilder() called on a non-Message type."); } - public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, - int index) { + @Override + public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) { throw new UnsupportedOperationException( "getRepeatedFieldBuilder() called on a non-Message type."); } @@ -2251,18 +2269,23 @@ public abstract class GeneratedMessage extends AbstractMessage clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); } + @Override public Object get(final GeneratedMessage message) { return invokeOrDie(getMethod, message); } + @Override public Object get(GeneratedMessage.Builder builder) { return invokeOrDie(getMethodBuilder, builder); } + @Override public Object getRaw(final GeneratedMessage message) { return get(message); } + @Override public Object getRaw(GeneratedMessage.Builder builder) { return get(builder); } + @Override public void set(final Builder builder, final Object value) { // Add all the elements individually. This serves two purposes: // 1) Verifies that each element has the correct type. @@ -2273,54 +2296,64 @@ public abstract class GeneratedMessage extends AbstractMessage addRepeated(builder, element); } } - public Object getRepeated(final GeneratedMessage message, - final int index) { + @Override + public Object getRepeated(final GeneratedMessage message, final int index) { return invokeOrDie(getRepeatedMethod, message, index); } + @Override public Object getRepeated(GeneratedMessage.Builder builder, int index) { return invokeOrDie(getRepeatedMethodBuilder, builder, index); } + @Override public Object getRepeatedRaw(GeneratedMessage message, int index) { return getRepeated(message, index); } - public Object getRepeatedRaw(GeneratedMessage.Builder builder, - int index) { + @Override + public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) { return getRepeated(builder, index); } - public void setRepeated(final Builder builder, - final int index, final Object value) { + @Override + public void setRepeated(final Builder builder, final int index, final Object value) { invokeOrDie(setRepeatedMethod, builder, index, value); } + @Override public void addRepeated(final Builder builder, final Object value) { invokeOrDie(addRepeatedMethod, builder, value); } + @Override public boolean has(final GeneratedMessage message) { throw new UnsupportedOperationException( "hasField() called on a repeated field."); } + @Override public boolean has(GeneratedMessage.Builder builder) { throw new UnsupportedOperationException( "hasField() called on a repeated field."); } + @Override public int getRepeatedCount(final GeneratedMessage message) { return (Integer) invokeOrDie(getCountMethod, message); } + @Override public int getRepeatedCount(GeneratedMessage.Builder builder) { return (Integer) invokeOrDie(getCountMethodBuilder, builder); } + @Override public void clear(final Builder builder) { invokeOrDie(clearMethod, builder); } + @Override public Message.Builder newBuilder() { throw new UnsupportedOperationException( "newBuilderForField() called on a non-Message type."); } + @Override public Message.Builder getBuilder(GeneratedMessage.Builder builder) { throw new UnsupportedOperationException( "getFieldBuilder() called on a non-Message type."); } - public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, - int index) { + @Override + public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) { throw new UnsupportedOperationException( "getRepeatedFieldBuilder() called on a non-Message type."); } @@ -2357,6 +2390,7 @@ public abstract class GeneratedMessage extends AbstractMessage field.getNumber()); } + @Override public Object get(GeneratedMessage message) { List result = new ArrayList(); for (int i = 0; i < getRepeatedCount(message); i++) { @@ -2365,6 +2399,7 @@ public abstract class GeneratedMessage extends AbstractMessage return Collections.unmodifiableList(result); } + @Override public Object get(Builder builder) { List result = new ArrayList(); for (int i = 0; i < getRepeatedCount(builder); i++) { @@ -2373,14 +2408,17 @@ public abstract class GeneratedMessage extends AbstractMessage return Collections.unmodifiableList(result); } + @Override public Object getRaw(GeneratedMessage message) { return get(message); } + @Override public Object getRaw(GeneratedMessage.Builder builder) { return get(builder); } + @Override public void set(Builder builder, Object value) { clear(builder); for (Object entry : (List) value) { @@ -2388,63 +2426,76 @@ public abstract class GeneratedMessage extends AbstractMessage } } + @Override public Object getRepeated(GeneratedMessage message, int index) { return getMapField(message).getList().get(index); } + @Override public Object getRepeated(Builder builder, int index) { return getMapField(builder).getList().get(index); } + @Override public Object getRepeatedRaw(GeneratedMessage message, int index) { return getRepeated(message, index); } + @Override public Object getRepeatedRaw(Builder builder, int index) { return getRepeated(builder, index); } + @Override public void setRepeated(Builder builder, int index, Object value) { getMutableMapField(builder).getMutableList().set(index, (Message) value); } + @Override public void addRepeated(Builder builder, Object value) { getMutableMapField(builder).getMutableList().add((Message) value); } + @Override public boolean has(GeneratedMessage message) { throw new UnsupportedOperationException( "hasField() is not supported for repeated fields."); } + @Override public boolean has(Builder builder) { throw new UnsupportedOperationException( "hasField() is not supported for repeated fields."); } + @Override public int getRepeatedCount(GeneratedMessage message) { return getMapField(message).getList().size(); } + @Override public int getRepeatedCount(Builder builder) { return getMapField(builder).getList().size(); } + @Override public void clear(Builder builder) { getMutableMapField(builder).getMutableList().clear(); } + @Override public com.google.protobuf.Message.Builder newBuilder() { return mapEntryMessageDefaultInstance.newBuilderForType(); } + @Override public com.google.protobuf.Message.Builder getBuilder(Builder builder) { throw new UnsupportedOperationException( "Nested builder not supported for map fields."); } - public com.google.protobuf.Message.Builder getRepeatedBuilder( - Builder builder, int index) { + @Override + public com.google.protobuf.Message.Builder getRepeatedBuilder(Builder builder, int index) { throw new UnsupportedOperationException( "Nested builder not supported for map fields."); } 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 12a1472d..c5adc5ad 100644 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java @@ -31,6 +31,7 @@ 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.FloatList; @@ -59,24 +60,27 @@ import java.util.Map; public abstract class GeneratedMessageLite< MessageType extends GeneratedMessageLite<MessageType, BuilderType>, BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>> - extends AbstractMessageLite { + extends AbstractMessageLite<MessageType, BuilderType> { /** For use by generated code only. Lazily initialized to reduce allocations. */ - protected UnknownFieldSetLite unknownFields = null; + protected UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance(); /** For use by generated code only. */ protected int memoizedSerializedSize = -1; + @Override @SuppressWarnings("unchecked") // Guaranteed by runtime. public final Parser<MessageType> getParserForType() { return (Parser<MessageType>) dynamicMethod(MethodToInvoke.GET_PARSER); } + @Override @SuppressWarnings("unchecked") // Guaranteed by runtime. public final MessageType getDefaultInstanceForType() { return (MessageType) dynamicMethod(MethodToInvoke.GET_DEFAULT_INSTANCE); } + @Override @SuppressWarnings("unchecked") // Guaranteed by runtime. public final BuilderType newBuilderForType() { return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER); @@ -99,7 +103,65 @@ public abstract class GeneratedMessageLite< return MessageLiteToString.toString(this, super.toString()); } + @SuppressWarnings("unchecked") // Guaranteed by runtime + @Override + public int hashCode() { + if (memoizedHashCode == 0) { + 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; + } + return memoizedHashCode; + } + + @SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (!getDefaultInstanceForType().getClass().isInstance(other)) { + 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)) { + return false; + } + visit(visitor, (MessageType) other); + return true; + } + // 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. @@ -108,7 +170,7 @@ public abstract class GeneratedMessageLite< * Lazily initializes unknown fields. */ private final void ensureUnknownFieldsInitialized() { - if (unknownFields == null) { + if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) { unknownFields = UnknownFieldSetLite.newInstance(); } } @@ -147,18 +209,18 @@ public abstract class GeneratedMessageLite< /** * Called by subclasses to complete parsing. For use by generated code only. */ - protected void doneParsing() { - if (unknownFields == null) { - unknownFields = UnknownFieldSetLite.getDefaultInstance(); - } else { - unknownFields.makeImmutable(); - } + protected void makeImmutable() { + dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE); + + unknownFields.makeImmutable(); } + @Override public final boolean isInitialized() { return dynamicMethod(MethodToInvoke.IS_INITIALIZED, Boolean.TRUE) != null; } + @Override public final BuilderType toBuilder() { BuilderType builder = (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER); builder.mergeFrom((MessageType) this); @@ -172,11 +234,14 @@ public abstract class GeneratedMessageLite< * For use by generated code only. */ public static enum MethodToInvoke { + // Rely on/modify instance state IS_INITIALIZED, - PARSE_PARTIAL_FROM, - MERGE_FROM, + VISIT, + MERGE_FROM_STREAM, MAKE_IMMUTABLE, - NEW_INSTANCE, + + // Rely on static state + NEW_MUTABLE_INSTANCE, NEW_BUILDER, GET_DEFAULT_INSTANCE, GET_PARSER; @@ -188,17 +253,18 @@ public abstract class GeneratedMessageLite< * builders in the runtime. This method bundles those operations to reduce the generated methods * count. * <ul> - * <li>{@code PARSE_PARTIAL_FROM} is parameterized with an {@link CodedInputStream} and + * <li>{@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 - * <li>{@code NEW_INSTANCE} returns a new instance of the protocol buffer + * implementation wraps it in a RuntimeException. + * <li>{@code NEW_INSTANCE} returns a new instance of the protocol buffer that has not yet been + * made immutable. See {@code MAKE_IMMUTABLE}. * <li>{@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. * <li>{@code NEW_BUILDER} returns a {@code BuilderType} instance. - * <li>{@code MERGE_FROM} is parameterized with a {@code MessageType} and merges the fields from - * that instance into this instance. + * <li>{@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. * <li>{@code MAKE_IMMUTABLE} sets all internal fields to an immutable state. * </ul> * This method, plus the implementation of the Builder, enables the Builder class to be proguarded @@ -222,6 +288,11 @@ public abstract class GeneratedMessageLite< return dynamicMethod(method, null, null); } + void visit(Visitor visitor, MessageType other) { + dynamicMethod(MethodToInvoke.VISIT, visitor, other); + unknownFields = visitor.visitUnknownFields(unknownFields, other.unknownFields); + } + /** * Merge some unknown fields into the {@link UnknownFieldSetLite} for this * message. @@ -236,7 +307,7 @@ public abstract class GeneratedMessageLite< public abstract static class Builder< MessageType extends GeneratedMessageLite<MessageType, BuilderType>, BuilderType extends Builder<MessageType, BuilderType>> - extends AbstractMessageLite.Builder<BuilderType> { + extends AbstractMessageLite.Builder<MessageType, BuilderType> { private final MessageType defaultInstance; protected MessageType instance; @@ -244,7 +315,8 @@ public abstract class GeneratedMessageLite< protected Builder(MessageType defaultInstance) { this.defaultInstance = defaultInstance; - this.instance = (MessageType) defaultInstance.dynamicMethod(MethodToInvoke.NEW_INSTANCE); + this.instance = + (MessageType) defaultInstance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE); isBuilt = false; } @@ -254,26 +326,27 @@ public abstract class GeneratedMessageLite< */ protected void copyOnWrite() { if (isBuilt) { - MessageType newInstance = (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_INSTANCE); - newInstance.dynamicMethod(MethodToInvoke.MERGE_FROM, instance); + MessageType newInstance = + (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE); + newInstance.visit(MergeFromVisitor.INSTANCE, instance); instance = newInstance; isBuilt = false; } } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public final boolean isInitialized() { return GeneratedMessageLite.isInitialized(instance, false /* shouldMemoize */); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public final BuilderType clear() { // No need to copy on write since we're dropping the instance anyways. - instance = (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_INSTANCE); + instance = (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE); return (BuilderType) this; } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public BuilderType clone() { BuilderType builder = (BuilderType) getDefaultInstanceForType().newBuilderForType(); @@ -281,20 +354,19 @@ public abstract class GeneratedMessageLite< return builder; } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public MessageType buildPartial() { if (isBuilt) { return instance; } - instance.dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE); - instance.unknownFields.makeImmutable(); + instance.makeImmutable(); isBuilt = true; return instance; } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public final MessageType build() { MessageType result = buildPartial(); if (!result.isInitialized()) { @@ -303,32 +375,36 @@ public abstract class GeneratedMessageLite< return result; } + @Override + protected BuilderType internalMergeFrom(MessageType message) { + return mergeFrom(message); + } + /** All subclasses implement this. */ public BuilderType mergeFrom(MessageType message) { copyOnWrite(); - instance.dynamicMethod(MethodToInvoke.MERGE_FROM, message); + instance.visit(MergeFromVisitor.INSTANCE, message); return (BuilderType) this; } + @Override public MessageType getDefaultInstanceForType() { return defaultInstance; } + @Override public BuilderType mergeFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - MessageType parsedMessage = null; + throws IOException { + copyOnWrite(); try { - parsedMessage = parsePartialFrom( - (MessageType) getDefaultInstanceForType(), input, extensionRegistry); - } catch (InvalidProtocolBufferException e) { - parsedMessage = (MessageType) e.getUnfinishedMessage(); - throw e; - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); + instance.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof IOException) { + throw (IOException) e.getCause(); } + throw e; } return (BuilderType) this; } @@ -384,6 +460,12 @@ public abstract class GeneratedMessageLite< } 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. @@ -521,9 +603,8 @@ public abstract class GeneratedMessageLite< } /** Check if a singular extension is present. */ - //@Override (Java 1.6 override semantics, but we must support 1.5) - public final <Type> boolean hasExtension( - final ExtensionLite<MessageType, Type> extension) { + @Override + public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extension) { GeneratedExtension<MessageType, Type> extensionLite = checkIsLite(extension); @@ -532,7 +613,7 @@ public abstract class GeneratedMessageLite< } /** Get the number of elements in a repeated extension. */ - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public final <Type> int getExtensionCount( final ExtensionLite<MessageType, List<Type>> extension) { GeneratedExtension<MessageType, List<Type>> extensionLite = @@ -543,10 +624,9 @@ public abstract class GeneratedMessageLite< } /** Get the value of an extension. */ - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override @SuppressWarnings("unchecked") - public final <Type> Type getExtension( - final ExtensionLite<MessageType, Type> extension) { + public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extension) { GeneratedExtension<MessageType, Type> extensionLite = checkIsLite(extension); @@ -560,11 +640,10 @@ public abstract class GeneratedMessageLite< } /** Get one element of a repeated extension. */ - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override @SuppressWarnings("unchecked") public final <Type> Type getExtension( - final ExtensionLite<MessageType, List<Type>> extension, - final int index) { + final ExtensionLite<MessageType, List<Type>> extension, final int index) { GeneratedExtension<MessageType, List<Type>> extensionLite = checkIsLite(extension); @@ -579,8 +658,8 @@ public abstract class GeneratedMessageLite< } @Override - protected final void doneParsing() { - super.doneParsing(); + protected final void makeImmutable() { + super.makeImmutable(); extensions.makeImmutable(); } @@ -669,7 +748,7 @@ public abstract class GeneratedMessageLite< instance.extensions = extensions; } - // @Override (Java 1.6 override semantics, but we must support 1.5) + @Override protected void copyOnWrite() { if (!isBuilt) { return; @@ -679,7 +758,7 @@ public abstract class GeneratedMessageLite< instance.extensions = instance.extensions.clone(); } - // @Override (Java 1.6 override semantics, but we must support 1.5) + @Override public final MessageType buildPartial() { if (isBuilt) { return instance; @@ -701,33 +780,30 @@ public abstract class GeneratedMessageLite< } /** Check if a singular extension is present. */ - //@Override (Java 1.6 override semantics, but we must support 1.5) - public final <Type> boolean hasExtension( - final ExtensionLite<MessageType, Type> extension) { + @Override + public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extension) { return instance.hasExtension(extension); } /** Get the number of elements in a repeated extension. */ - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public final <Type> int getExtensionCount( final ExtensionLite<MessageType, List<Type>> extension) { return instance.getExtensionCount(extension); } /** Get the value of an extension. */ - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override @SuppressWarnings("unchecked") - public final <Type> Type getExtension( - final ExtensionLite<MessageType, Type> extension) { + public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extension) { return instance.getExtension(extension); } /** Get one element of a repeated extension. */ + @Override @SuppressWarnings("unchecked") - //@Override (Java 1.6 override semantics, but we must support 1.5) public final <Type> Type getExtension( - final ExtensionLite<MessageType, List<Type>> extension, - final int index) { + final ExtensionLite<MessageType, List<Type>> extension, final int index) { return instance.getExtension(extension, index); } @@ -859,37 +935,44 @@ public abstract class GeneratedMessageLite< final boolean isRepeated; final boolean isPacked; + @Override public int getNumber() { return number; } + @Override public WireFormat.FieldType getLiteType() { return type; } + @Override public WireFormat.JavaType getLiteJavaType() { return type.getJavaType(); } + @Override public boolean isRepeated() { return isRepeated; } + @Override public boolean isPacked() { return isPacked; } + @Override public Internal.EnumLiteMap<?> getEnumType() { return enumTypeMap; } + @Override @SuppressWarnings("unchecked") - public MessageLite.Builder internalMergeFrom( - MessageLite.Builder to, MessageLite from) { + public MessageLite.Builder internalMergeFrom(MessageLite.Builder to, MessageLite from) { return ((Builder) to).mergeFrom((GeneratedMessageLite) from); } + @Override public int compareTo(ExtensionDescriptor other) { return number - other.number; } @@ -984,6 +1067,7 @@ public abstract class GeneratedMessageLite< } /** Get the field number. */ + @Override public int getNumber() { return descriptor.getNumber(); } @@ -993,6 +1077,7 @@ public abstract class GeneratedMessageLite< * If the extension is an embedded message or group, returns the default * instance of the message. */ + @Override public MessageLite getMessageDefaultInstance() { return messageDefaultInstance; } @@ -1047,14 +1132,17 @@ public abstract class GeneratedMessageLite< } } + @Override public FieldType getLiteType() { return descriptor.getLiteType(); } + @Override public boolean isRepeated() { return descriptor.isRepeated; } + @Override public Type getDefaultValue() { return defaultValue; } @@ -1139,112 +1227,72 @@ public abstract class GeneratedMessageLite< protected static final <T extends GeneratedMessageLite<T, ?>> boolean isInitialized( T message, boolean shouldMemoize) { return message.dynamicMethod(MethodToInvoke.IS_INITIALIZED, shouldMemoize) != null; - } + } protected static final <T extends GeneratedMessageLite<T, ?>> void makeImmutable(T message) { message.dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE); } - - protected static IntList newIntList() { - return new IntArrayList(); - } - - protected static IntList newIntListWithCapacity(int capacity) { - return new IntArrayList(capacity); - } - - protected static IntList newIntList(List<Integer> toCopy) { - return new IntArrayList(toCopy); - } - + protected static IntList emptyIntList() { return IntArrayList.emptyList(); } - protected static LongList newLongList() { - return new LongArrayList(); + protected static IntList mutableCopy(IntList list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); } - protected static LongList newLongListWithCapacity(int capacity) { - return new LongArrayList(capacity); - } - - protected static LongList newLongList(List<Long> toCopy) { - return new LongArrayList(toCopy); - } - protected static LongList emptyLongList() { return LongArrayList.emptyList(); } - protected static FloatList newFloatList() { - return new FloatArrayList(); + protected static LongList mutableCopy(LongList list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); } - - protected static FloatList newFloatListWithCapacity(int capacity) { - return new FloatArrayList(capacity); - } - - protected static FloatList newFloatList(List<Float> toCopy) { - return new FloatArrayList(toCopy); - } - + protected static FloatList emptyFloatList() { return FloatArrayList.emptyList(); } - protected static DoubleList newDoubleList() { - return new DoubleArrayList(); + protected static FloatList mutableCopy(FloatList list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); } - - protected static DoubleList newDoubleListWithCapacity(int capacity) { - return new DoubleArrayList(capacity); - } - - protected static DoubleList newDoubleList(List<Double> toCopy) { - return new DoubleArrayList(toCopy); - } - + protected static DoubleList emptyDoubleList() { return DoubleArrayList.emptyList(); } - protected static BooleanList newBooleanList() { - return new BooleanArrayList(); - } - - protected static BooleanList newBooleanListWithCapacity(int capacity) { - return new BooleanArrayList(capacity); + protected static DoubleList mutableCopy(DoubleList list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); } - - protected static BooleanList newBooleanList(List<Boolean> toCopy) { - return new BooleanArrayList(toCopy); - } - + protected static BooleanList emptyBooleanList() { return BooleanArrayList.emptyList(); } - protected static <E> ProtobufList<E> newProtobufList() { - return new ProtobufArrayList<E>(); - } - - protected static <E> ProtobufList<E> newProtobufList(List<E> toCopy) { - return new ProtobufArrayList<E>(toCopy); - } - - protected static <E> ProtobufList<E> newProtobufListWithCapacity(int capacity) { - return new ProtobufArrayList<E>(capacity); + protected static BooleanList mutableCopy(BooleanList list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); } - + protected static <E> ProtobufList<E> emptyProtobufList() { return ProtobufArrayList.emptyList(); } - - protected static LazyStringArrayList emptyLazyStringArrayList() { - return LazyStringArrayList.emptyList(); - } + protected static <E> ProtobufList<E> mutableCopy(ProtobufList<E> list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + } + /** * A {@link Parser} implementation that delegates to the default instance. * <p> @@ -1274,10 +1322,11 @@ public abstract class GeneratedMessageLite< static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom( T instance, CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { - T result; + @SuppressWarnings("unchecked") // Guaranteed by protoc + T result = (T) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE); try { - result = (T) instance.dynamicMethod( - MethodToInvoke.PARSE_PARTIAL_FROM, input, extensionRegistry); + result.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry); + result.makeImmutable(); } catch (RuntimeException e) { if (e.getCause() instanceof InvalidProtocolBufferException) { throw (InvalidProtocolBufferException) e.getCause(); @@ -1454,4 +1503,740 @@ public abstract class GeneratedMessageLite< } 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 visitOneofLazyMessage(boolean minePresent, Object mine, Object other); + Object visitOneofMessage(boolean minePresent, Object mine, Object other); + void visitOneofNotSet(boolean minePresent); + + /** + * Message fields use null sentinals. + */ + <T extends MessageLite> T visitMessage(T mine, T other); + LazyFieldLite visitLazyMessage( + boolean minePresent, LazyFieldLite mine, boolean otherPresent, LazyFieldLite other); + + <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> 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<ExtensionDescriptor> visitExtensions( + FieldSet<ExtensionDescriptor> mine, FieldSet<ExtensionDescriptor> other); + UnknownFieldSetLite visitUnknownFields(UnknownFieldSetLite mine, UnknownFieldSetLite other); + <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> 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 visitOneofLazyMessage(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 extends MessageLite> 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 LazyFieldLite visitLazyMessage( + boolean minePresent, LazyFieldLite mine, boolean otherPresent, LazyFieldLite other) { + if (!minePresent && !otherPresent) { + return mine; + } else if (minePresent && otherPresent && mine.equals(other)) { + return mine; + } + throw NOT_EQUALS; + } + + @Override + public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> 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<ExtensionDescriptor> visitExtensions( + FieldSet<ExtensionDescriptor> mine, + FieldSet<ExtensionDescriptor> 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 <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other) { + if (!mine.equals(other)) { + throw NOT_EQUALS; + } + return mine; + } + } + + /** + * Implements hashCode by accumulating state. + */ + private 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. + + private 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 visitOneofLazyMessage(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 extends MessageLite> 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 LazyFieldLite visitLazyMessage( + boolean minePresent, LazyFieldLite mine, boolean otherPresent, LazyFieldLite other) { + hashCode = (53 * hashCode) + mine.hashCode(); + return mine; + } + + @Override + public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> 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<ExtensionDescriptor> visitExtensions( + FieldSet<ExtensionDescriptor> mine, + FieldSet<ExtensionDescriptor> 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 <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> 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 visitOneofLazyMessage(boolean minePresent, Object mine, Object other) { + if (minePresent) { + LazyFieldLite lazy = (LazyFieldLite) mine; + lazy.merge((LazyFieldLite) other); + return lazy; + } + 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 extends MessageLite> 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 LazyFieldLite visitLazyMessage( + boolean minePresent, LazyFieldLite mine, boolean otherPresent, LazyFieldLite other) { + // LazyFieldLite's are never null so we can just copy across. Necessary to avoid leakage + // from builder into immutable message. + // TODO(dweis): Change to null sentinels? + mine.merge(other); + return mine; + } + + @Override + public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> 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<ExtensionDescriptor> visitExtensions( + FieldSet<ExtensionDescriptor> mine, + FieldSet<ExtensionDescriptor> 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 <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other) { + mine.mergeFrom(other); + return mine; + } + } } 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 f4e68ed8..6d6ece5a 100644 --- a/java/core/src/main/java/com/google/protobuf/IntArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/IntArrayList.java @@ -34,7 +34,6 @@ import com.google.protobuf.Internal.IntList; import java.util.Arrays; import java.util.Collection; -import java.util.List; import java.util.RandomAccess; /** @@ -44,8 +43,6 @@ import java.util.RandomAccess; */ final class IntArrayList extends AbstractProtobufList<Integer> implements IntList, RandomAccess { - private static final int DEFAULT_CAPACITY = 10; - private static final IntArrayList EMPTY_LIST = new IntArrayList(); static { EMPTY_LIST.makeImmutable(); @@ -70,32 +67,55 @@ final class IntArrayList extends AbstractProtobufList<Integer> implements IntLis * Constructs a new mutable {@code IntArrayList} with default capacity. */ IntArrayList() { - this(DEFAULT_CAPACITY); - } - - /** - * Constructs a new mutable {@code IntArrayList} with the provided capacity. - */ - IntArrayList(int capacity) { - array = new int[capacity]; - size = 0; + this(new int[DEFAULT_CAPACITY], 0); } /** * Constructs a new mutable {@code IntArrayList} containing the same elements as {@code other}. */ - IntArrayList(List<Integer> other) { - if (other instanceof IntArrayList) { - IntArrayList list = (IntArrayList) other; - array = list.array.clone(); - size = list.size; - } else { - size = other.size(); - array = new int[size]; - for (int i = 0; i < size; i++) { - array[i] = other.get(i); + private IntArrayList(int[] array, int size) { + this.array = array; + this.size = size; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof IntArrayList)) { + return super.equals(o); + } + IntArrayList other = (IntArrayList) o; + if (size != other.size) { + return false; + } + + final int[] arr = other.array; + for (int i = 0; i < size; i++) { + if (array[i] != arr[i]) { + return false; } } + + return true; + } + + @Override + public int hashCode() { + int result = 1; + for (int i = 0; i < size; i++) { + result = (31 * result) + array[i]; + } + return result; + } + + @Override + public IntList mutableCopyWithCapacity(int capacity) { + if (capacity < size) { + throw new IllegalArgumentException(); + } + return new IntArrayList(Arrays.copyOf(array, capacity), size); } @Override 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 abf7ddd6..d1de375e 100644 --- a/java/core/src/main/java/com/google/protobuf/Internal.java +++ b/java/core/src/main/java/com/google/protobuf/Internal.java @@ -41,6 +41,7 @@ import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.RandomAccess; import java.util.Set; /** @@ -457,10 +458,13 @@ public final class Internal { public static <T extends EnumLite> Converter<Integer, T> newEnumConverter( final EnumLiteMap<T> enumMap, final T unrecognizedValue) { return new Converter<Integer, T>() { + @Override public T doForward(Integer value) { T result = enumMap.findValueByNumber(value); return result == null ? unrecognizedValue : result; } + + @Override public Integer doBackward(T value) { return value.getNumber(); } @@ -573,8 +577,10 @@ public final class Internal { /** * Extends {@link List} to add the capability to make the list immutable and inspect if it is * modifiable. + * <p> + * All implementations must support efficient random access. */ - public static interface ProtobufList<E> extends List<E> { + public static interface ProtobufList<E> extends List<E>, RandomAccess { /** * Makes this list immutable. All subsequent modifications will throw an @@ -586,6 +592,11 @@ public final class Internal { * Returns whether this list can be modified via the publicly accessible {@link List} methods. */ boolean isModifiable(); + + /** + * Returns a mutable clone of this list with the specified capacity. + */ + ProtobufList<E> mutableCopyWithCapacity(int capacity); } /** @@ -600,14 +611,20 @@ public final class Internal { int getInt(int index); /** - * Like {@link #add(Object)} 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. */ void addInt(int element); /** - * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. + * Like {@link #set(int, Integer)} 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. + */ + @Override + IntList mutableCopyWithCapacity(int capacity); } /** @@ -622,14 +639,20 @@ public final class Internal { boolean getBoolean(int index); /** - * Like {@link #add(Object)} 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. */ void addBoolean(boolean element); /** - * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. + * Like {@link #set(int, Boolean)} 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. + */ + @Override + BooleanList mutableCopyWithCapacity(int capacity); } /** @@ -644,14 +667,20 @@ public final class Internal { long getLong(int index); /** - * Like {@link #add(Object)} 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. */ void addLong(long element); /** - * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. + * Like {@link #set(int, Long)} 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. + */ + @Override + LongList mutableCopyWithCapacity(int capacity); } /** @@ -666,14 +695,20 @@ public final class Internal { double getDouble(int index); /** - * Like {@link #add(Object)} 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. */ void addDouble(double element); /** - * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. + * Like {@link #set(int, Double)} 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. + */ + @Override + DoubleList mutableCopyWithCapacity(int capacity); } /** @@ -688,13 +723,19 @@ public final class Internal { float getFloat(int index); /** - * Like {@link #add(Object)} 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. */ void addFloat(float element); /** - * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. + * Like {@link #set(int, Float)} 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. + */ + @Override + FloatList mutableCopyWithCapacity(int capacity); } } 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 3da8b900..98e13ca1 100644 --- a/java/core/src/main/java/com/google/protobuf/LazyField.java +++ b/java/core/src/main/java/com/google/protobuf/LazyField.java @@ -95,12 +95,12 @@ public class LazyField extends LazyFieldLite { this.entry = entry; } - // @Override + @Override public K getKey() { return entry.getKey(); } - // @Override + @Override public Object getValue() { LazyField field = entry.getValue(); if (field == null) { @@ -113,7 +113,7 @@ public class LazyField extends LazyFieldLite { return entry.getValue(); } - // @Override + @Override public Object setValue(Object value) { if (!(value instanceof MessageLite)) { throw new IllegalArgumentException( @@ -131,13 +131,13 @@ public class LazyField extends LazyFieldLite { this.iterator = iterator; } - // @Override + @Override public boolean hasNext() { return iterator.hasNext(); } + @Override @SuppressWarnings("unchecked") - // @Override public Entry<K, Object> next() { Entry<K, ?> entry = iterator.next(); if (entry.getValue() instanceof LazyField) { @@ -146,7 +146,7 @@ public class LazyField extends LazyFieldLite { return (Entry<K, Object>) entry; } - // @Override + @Override public void remove() { iterator.remove(); } 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 016ec20d..2febaace 100644 --- a/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java +++ b/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java @@ -135,6 +135,43 @@ public class LazyFieldLite { return lf; } + @Override + 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 + // messages can by unequal but then be turned equal simply be invoking a getter on a lazy field. + MessageLite value1 = value; + MessageLite value2 = other.value; + if (value1 == null && value2 == null) { + return toByteString().equals(other.toByteString()); + } else if (value1 != null && value2 != null) { + return value1.equals(value2); + } else if (value1 != null) { + return value1.equals(other.getValue(value1.getDefaultInstanceForType())); + } else { + 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 + // hash codes but evaluate to equivalent messages. And we have no facility for constructing + // 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. */ @@ -340,6 +377,8 @@ public class LazyFieldLite { * 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 + // have memoized serialized size based off of it. if (memoizedBytes != null) { return memoizedBytes.size(); } else if (delayedBytes != null) { @@ -358,6 +397,8 @@ public class LazyFieldLite { if (memoizedBytes != null) { return memoizedBytes; } + // We *must* return delayed bytes if it was set because the dependent messages may have + // memoized serialized size based off of it. if (delayedBytes != null) { return delayedBytes; } 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 68c430cf..d474c51e 100644 --- a/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java @@ -64,7 +64,7 @@ import java.util.RandomAccess; */ public class LazyStringArrayList extends AbstractProtobufList<String> implements LazyStringList, RandomAccess { - + private static final LazyStringArrayList EMPTY_LIST = new LazyStringArrayList(); static { EMPTY_LIST.makeImmutable(); @@ -80,11 +80,11 @@ public class LazyStringArrayList extends AbstractProtobufList<String> private final List<Object> list; public LazyStringArrayList() { - list = new ArrayList<Object>(); + this(DEFAULT_CAPACITY); } public LazyStringArrayList(int intialCapacity) { - list = new ArrayList<Object>(intialCapacity); + this(new ArrayList<Object>(intialCapacity)); } public LazyStringArrayList(LazyStringList from) { @@ -93,7 +93,21 @@ public class LazyStringArrayList extends AbstractProtobufList<String> } public LazyStringArrayList(List<String> from) { - list = new ArrayList<Object>(from); + this(new ArrayList<Object>(from)); + } + + private LazyStringArrayList(ArrayList<Object> list) { + this.list = list; + } + + @Override + public LazyStringArrayList mutableCopyWithCapacity(int capacity) { + if (capacity < size()) { + throw new IllegalArgumentException(); + } + ArrayList<Object> newList = new ArrayList<Object>(capacity); + newList.addAll(list); + return new LazyStringArrayList(newList); } @Override @@ -170,7 +184,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> return ret; } - // @Override + @Override public boolean addAllByteString(Collection<? extends ByteString> values) { ensureIsMutable(); boolean ret = list.addAll(values); @@ -178,7 +192,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> return ret; } - // @Override + @Override public boolean addAllByteArray(Collection<byte[]> c) { ensureIsMutable(); boolean ret = list.addAll(c); @@ -201,14 +215,14 @@ public class LazyStringArrayList extends AbstractProtobufList<String> modCount++; } - // @Override + @Override public void add(ByteString element) { ensureIsMutable(); list.add(element); modCount++; } - // @Override + @Override public void add(byte[] element) { ensureIsMutable(); list.add(element); @@ -220,7 +234,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> return list.get(index); } - // @Override + @Override public ByteString getByteString(int index) { Object o = list.get(index); ByteString b = asByteString(o); @@ -230,7 +244,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> return b; } - // @Override + @Override public byte[] getByteArray(int index) { Object o = list.get(index); byte[] b = asByteArray(o); @@ -240,7 +254,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> return b; } - // @Override + @Override public void set(int index, ByteString s) { setAndReturn(index, s); } @@ -250,7 +264,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> return list.set(index, s); } - // @Override + @Override public void set(int index, byte[] s) { setAndReturn(index, s); } @@ -290,12 +304,12 @@ public class LazyStringArrayList extends AbstractProtobufList<String> } } - // @Override + @Override public List<?> getUnderlyingElements() { return Collections.unmodifiableList(list); } - // @Override + @Override public void mergeFrom(LazyStringList other) { ensureIsMutable(); for (Object o : other.getUnderlyingElements()) { @@ -349,7 +363,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String> } } - // @Override + @Override public List<byte[]> asByteArrayList() { return new ByteArrayListView(this); } @@ -393,12 +407,12 @@ public class LazyStringArrayList extends AbstractProtobufList<String> } } - // @Override + @Override public List<ByteString> asByteStringList() { return new ByteStringListView(this); } - // @Override + @Override public LazyStringList getUnmodifiableView() { if (isModifiable()) { return new UnmodifiableLazyStringList(this); 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 ebe62029..bc4475d1 100644 --- a/java/core/src/main/java/com/google/protobuf/LongArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/LongArrayList.java @@ -34,7 +34,6 @@ import com.google.protobuf.Internal.LongList; import java.util.Arrays; import java.util.Collection; -import java.util.List; import java.util.RandomAccess; /** @@ -44,8 +43,6 @@ import java.util.RandomAccess; */ final class LongArrayList extends AbstractProtobufList<Long> implements LongList, RandomAccess { - private static final int DEFAULT_CAPACITY = 10; - private static final LongArrayList EMPTY_LIST = new LongArrayList(); static { EMPTY_LIST.makeImmutable(); @@ -70,32 +67,55 @@ final class LongArrayList extends AbstractProtobufList<Long> implements LongList * Constructs a new mutable {@code LongArrayList} with default capacity. */ LongArrayList() { - this(DEFAULT_CAPACITY); - } - - /** - * Constructs a new mutable {@code LongArrayList} with the provided capacity. - */ - LongArrayList(int capacity) { - array = new long[capacity]; - size = 0; + this(new long[DEFAULT_CAPACITY], 0); } /** * Constructs a new mutable {@code LongArrayList} containing the same elements as {@code other}. */ - LongArrayList(List<Long> other) { - if (other instanceof LongArrayList) { - LongArrayList list = (LongArrayList) other; - array = list.array.clone(); - size = list.size; - } else { - size = other.size(); - array = new long[size]; - for (int i = 0; i < size; i++) { - array[i] = other.get(i); + private LongArrayList(long[] array, int size) { + this.array = array; + this.size = size; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof IntArrayList)) { + return super.equals(o); + } + LongArrayList other = (LongArrayList) o; + if (size != other.size) { + return false; + } + + final long[] arr = other.array; + for (int i = 0; i < size; i++) { + if (array[i] != arr[i]) { + return false; } } + + return true; + } + + @Override + public int hashCode() { + int result = 1; + for (int i = 0; i < size; i++) { + result = (31 * result) + Internal.hashLong(array[i]); + } + return result; + } + + @Override + public LongList mutableCopyWithCapacity(int capacity) { + if (capacity < size) { + throw new IllegalArgumentException(); + } + return new LongArrayList(Arrays.copyOf(array, capacity), size); } @Override 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 bcffa946..12c64abb 100644 --- a/java/core/src/main/java/com/google/protobuf/MapEntryLite.java +++ b/java/core/src/main/java/com/google/protobuf/MapEntryLite.java @@ -41,7 +41,8 @@ import java.io.IOException; * * Protobuf internal. Users shouldn't use. */ -public class MapEntryLite<K, V> extends AbstractMessageLite { +public class MapEntryLite<K, V> + extends AbstractMessageLite<MapEntryLite<K, V>, MapEntryLite.Builder<K, V>> { private static class Metadata<K, V> { public final MapEntryLite<K, V> defaultInstance; public final WireFormat.FieldType keyType; @@ -233,7 +234,7 @@ public class MapEntryLite<K, V> extends AbstractMessageLite { * Builder used to create {@link MapEntryLite} messages. */ public static class Builder<K, V> - extends AbstractMessageLite.Builder<Builder<K, V>> { + extends AbstractMessageLite.Builder<MapEntryLite<K, V>, Builder<K, V>> { private final Metadata<K, V> metadata; private K key; private V value; @@ -327,5 +328,10 @@ public class MapEntryLite<K, V> extends AbstractMessageLite { this.value = entry.value; return this; } + + @Override + protected Builder<K, V> internalMergeFrom(MapEntryLite<K, V> message) { + throw new UnsupportedOperationException(); + } } } 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 b290993c..907f0f71 100644 --- a/java/core/src/main/java/com/google/protobuf/MapField.java +++ b/java/core/src/main/java/com/google/protobuf/MapField.java @@ -93,15 +93,18 @@ public class MapField<K, V> implements MutabilityOracle { this.defaultEntry = defaultEntry; } + @Override public Message convertKeyAndValueToMessage(K key, V value) { return defaultEntry.newBuilderForType().setKey(key).setValue(value).buildPartial(); } + @Override public void convertMessageToKeyAndValue(Message message, Map<K, V> map) { MapEntry<K, V> entry = (MapEntry<K, V>) message; map.put(entry.getKey(), entry.getValue()); } + @Override public Message getMessageDefaultInstance() { return defaultEntry; } 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 9516d71f..94590fb9 100644 --- a/java/core/src/main/java/com/google/protobuf/Message.java +++ b/java/core/src/main/java/com/google/protobuf/Message.java @@ -51,6 +51,7 @@ import java.util.Map; public interface Message extends MessageLite, MessageOrBuilder { // (From MessageLite, re-declared here only for return type covariance.) + @Override Parser<? extends Message> getParserForType(); @@ -97,7 +98,10 @@ public interface Message extends MessageLite, MessageOrBuilder { // Builders // (From MessageLite, re-declared here only for return type covariance.) + @Override Builder newBuilderForType(); + + @Override Builder toBuilder(); /** @@ -106,6 +110,7 @@ public interface Message extends MessageLite, MessageOrBuilder { interface Builder extends MessageLite.Builder, MessageOrBuilder { // (From MessageLite.Builder, re-declared here only for return type // covariance.) + @Override Builder clear(); /** @@ -131,18 +136,27 @@ public interface Message extends MessageLite, MessageOrBuilder { // (From MessageLite.Builder, re-declared here only for return type // covariance.) + @Override Message build(); + + @Override Message buildPartial(); + + @Override Builder clone(); + + @Override Builder mergeFrom(CodedInputStream input) throws IOException; - Builder mergeFrom(CodedInputStream input, - ExtensionRegistryLite extensionRegistry) - throws IOException; + + @Override + Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry) + throws IOException; /** * Get the message's type's descriptor. * See {@link Message#getDescriptorForType()}. */ + @Override Descriptors.Descriptor getDescriptorForType(); /** @@ -240,27 +254,39 @@ public interface Message extends MessageLite, MessageOrBuilder { // (From MessageLite.Builder, re-declared here only for return type // covariance.) + @Override Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException; - Builder mergeFrom(ByteString data, - ExtensionRegistryLite extensionRegistry) - throws InvalidProtocolBufferException; + + @Override + Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + @Override Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException; - Builder mergeFrom(byte[] data, int off, int len) - throws InvalidProtocolBufferException; - Builder mergeFrom(byte[] data, - ExtensionRegistryLite extensionRegistry) - throws InvalidProtocolBufferException; - Builder mergeFrom(byte[] data, int off, int len, - ExtensionRegistryLite extensionRegistry) - throws InvalidProtocolBufferException; + + @Override + Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException; + + @Override + Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + @Override + Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + @Override Builder mergeFrom(InputStream input) throws IOException; - Builder mergeFrom(InputStream input, - ExtensionRegistryLite extensionRegistry) - throws IOException; - boolean mergeDelimitedFrom(InputStream input) - throws IOException; - boolean mergeDelimitedFrom(InputStream input, - ExtensionRegistryLite extensionRegistry) - throws IOException; + + @Override + Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry) + throws IOException; + + @Override + boolean mergeDelimitedFrom(InputStream input) throws IOException; + + @Override + boolean mergeDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry) + throws IOException; } } 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 798b7943..88f531df 100644 --- a/java/core/src/main/java/com/google/protobuf/MessageLite.java +++ b/java/core/src/main/java/com/google/protobuf/MessageLite.java @@ -295,6 +295,27 @@ public interface MessageLite extends MessageLiteOrBuilder { 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())}). + * + * Merging occurs as follows. For each field:<br> + * * For singular primitive fields, if the field is set in {@code other}, + * then {@code other}'s value overwrites the value in this message.<br> + * * 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.<br> + * * 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++. + */ + Builder mergeFrom(MessageLite other); /** * Like {@link #mergeFrom(InputStream)}, but does not read until EOF. 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 2a6e0e30..43847651 100644 --- a/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java +++ b/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java @@ -30,23 +30,24 @@ package com.google.protobuf; -import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.TreeSet; /** * Helps generate {@link String} representations of {@link MessageLite} protos. */ +// TODO(dweis): Fix map fields. final class MessageLiteToString { - /** - * Suffix for *_FIELD_NUMBER fields. This is used to reflectively detect proto fields that should - * be toString()ed. - */ - private static final String FIELD_NUMBER_NAME_SUFFIX = "_FIELD_NUMBER"; + private static final String LIST_SUFFIX = "List"; + private static final String BUILDER_LIST_SUFFIX = "OrBuilderList"; + private static final String BYTES_SUFFIX = "Bytes"; + /** * 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 @@ -73,52 +74,70 @@ final class MessageLiteToString { // 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. Map<String, Method> nameToNoArgMethod = new HashMap<String, Method>(); + Map<String, Method> nameToMethod = new HashMap<String, Method>(); + Set<String> getters = new TreeSet<String>(); for (Method method : messageLite.getClass().getDeclaredMethods()) { + nameToMethod.put(method.getName(), method); if (method.getParameterTypes().length == 0) { nameToNoArgMethod.put(method.getName(), method); + + if (method.getName().startsWith("get")) { + getters.add(method.getName()); + } } } - for (Field field : messageLite.getClass().getDeclaredFields()) { - String fieldName = field.getName(); - // Skip all fields that aren't in a format like "FOO_BAR_FIELD_NUMBER" - if (!fieldName.endsWith(FIELD_NUMBER_NAME_SUFFIX)) { - continue; + 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()); + // 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); + if (listMethod != null) { + printField( + buffer, + indent, + camelCaseToSnakeCase(camelCase), + GeneratedMessageLite.invokeOrDie(listMethod, messageLite)); + continue; + } } - // For "FOO_BAR_FIELD_NUMBER" his would be "FOO_BAR" - String upperUnderscore = - fieldName.substring(0, fieldName.length() - FIELD_NUMBER_NAME_SUFFIX.length()); - - // For "FOO_BAR_FIELD_NUMBER" his would be "FooBar" - String upperCamelCaseName = upperUnderscoreToUpperCamel(upperUnderscore); + Method setter = nameToMethod.get("set" + suffix); + if (setter == null) { + continue; + } + if (suffix.endsWith(BYTES_SUFFIX) + && nameToNoArgMethod.containsKey( + "get" + suffix.substring(0, suffix.length() - "Bytes".length()))) { + // Heuristic to skip bytes based accessors for string fields. + continue; + } + + 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. - Method getMethod = nameToNoArgMethod.get("get" + upperCamelCaseName); - Method hasMethod = nameToNoArgMethod.get("has" + upperCamelCaseName); - if (getMethod != null && hasMethod != null) { - if ((Boolean) GeneratedMessageLite.invokeOrDie(hasMethod, messageLite)) { + 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. + if (hasValue) { printField( buffer, indent, - upperUnderscore.toLowerCase(), - GeneratedMessageLite.invokeOrDie(getMethod, messageLite)); + camelCaseToSnakeCase(camelCase), + value); } continue; } - - // 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" + upperCamelCaseName + "List"); - if (listMethod != null) { - printField( - buffer, - indent, - upperUnderscore.toLowerCase(), - GeneratedMessageLite.invokeOrDie(listMethod, messageLite)); - continue; - } } if (messageLite instanceof GeneratedMessageLite.ExtendableMessage) { @@ -130,10 +149,39 @@ final class MessageLiteToString { } } - if (((GeneratedMessageLite) messageLite).unknownFields != null) { - ((GeneratedMessageLite) messageLite).unknownFields.printWithIndent(buffer, indent); + if (((GeneratedMessageLite<?, ?>) messageLite).unknownFields != null) { + ((GeneratedMessageLite<?, ?>) messageLite).unknownFields.printWithIndent(buffer, indent); } } + + private static boolean isDefaultValue(Object o) { + if (o instanceof Boolean) { + return !((Boolean) o); + } + if (o instanceof Integer) { + return ((Integer) o) == 0; + } + if (o instanceof Float) { + return ((Float) o) == 0f; + } + if (o instanceof Double) { + return ((Double) o) == 0d; + } + if (o instanceof String) { + return o.equals(""); + } + if (o instanceof ByteString) { + return o.equals(ByteString.EMPTY); + } + if (o instanceof MessageLite) { // Can happen in oneofs. + return o == ((MessageLite) o).getDefaultInstanceForType(); + } + if (o instanceof java.lang.Enum<?>) { // Catches oneof enums. + return ((java.lang.Enum<?>) o).ordinal() == 0; + } + + return false; + } /** * Formats a text proto field. @@ -166,7 +214,7 @@ final class MessageLiteToString { buffer.append(": \"").append(TextFormatEscaper.escapeBytes((ByteString) object)).append('"'); } else if (object instanceof GeneratedMessageLite) { buffer.append(" {"); - reflectivePrintWithIndent((GeneratedMessageLite) object, buffer, indent + 2); + reflectivePrintWithIndent((GeneratedMessageLite<?, ?>) object, buffer, indent + 2); buffer.append("\n"); for (int i = 0; i < indent; i++) { buffer.append(' '); @@ -176,25 +224,16 @@ final class MessageLiteToString { buffer.append(": ").append(object.toString()); } } - - /** - * A Guava-less implementation of: - * {@code CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, upperUnderscore)} - */ - private static String upperUnderscoreToUpperCamel(String upperUnderscore) { - String upperCamelCaseName = ""; - boolean nextCharacterShouldBeUpper = true; - for (int i = 0; i < upperUnderscore.length(); i++) { - char ch = upperUnderscore.charAt(i); - if (ch == '_') { - nextCharacterShouldBeUpper = true; - } else if (nextCharacterShouldBeUpper){ - upperCamelCaseName += Character.toUpperCase(ch); - nextCharacterShouldBeUpper = false; - } else { - upperCamelCaseName += Character.toLowerCase(ch); + + private static final String camelCaseToSnakeCase(String camelCase) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < camelCase.length(); i++) { + char ch = camelCase.charAt(i); + if (Character.isUpperCase(ch)) { + builder.append("_"); } + builder.append(Character.toLowerCase(ch)); } - return upperCamelCaseName; + return builder.toString(); } } 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 f0fc4859..5e7d7821 100644 --- a/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java +++ b/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java @@ -42,7 +42,7 @@ import java.util.Map; public interface MessageOrBuilder extends MessageLiteOrBuilder { // (From MessageLite, re-declared here only for return type covariance.) - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override Message getDefaultInstanceForType(); /** 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 de4bfd3e..7b791d9e 100644 --- a/java/core/src/main/java/com/google/protobuf/MessageReflection.java +++ b/java/core/src/main/java/com/google/protobuf/MessageReflection.java @@ -364,12 +364,14 @@ class MessageReflection { * Finishes the merge and returns the underlying object. */ Object finish(); + } static class BuilderAdapter implements MergeTarget { private final Message.Builder builder; + @Override public Descriptors.Descriptor getDescriptorForType() { return builder.getDescriptorForType(); } @@ -378,6 +380,7 @@ class MessageReflection { this.builder = builder; } + @Override public Object getField(Descriptors.FieldDescriptor field) { return builder.getField(field); } @@ -387,25 +390,27 @@ class MessageReflection { return builder.hasField(field); } - public MergeTarget setField(Descriptors.FieldDescriptor field, - Object value) { + @Override + public MergeTarget setField(Descriptors.FieldDescriptor field, Object value) { builder.setField(field, value); return this; } + @Override public MergeTarget clearField(Descriptors.FieldDescriptor field) { builder.clearField(field); return this; } + @Override public MergeTarget setRepeatedField( Descriptors.FieldDescriptor field, int index, Object value) { builder.setRepeatedField(field, index, value); return this; } - public MergeTarget addRepeatedField( - Descriptors.FieldDescriptor field, Object value) { + @Override + public MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, Object value) { builder.addRepeatedField(field, value); return this; } @@ -426,25 +431,30 @@ class MessageReflection { return builder.getOneofFieldDescriptor(oneof); } + @Override public ContainerType getContainerType() { return ContainerType.MESSAGE; } + @Override public ExtensionRegistry.ExtensionInfo findExtensionByName( ExtensionRegistry registry, String name) { return registry.findImmutableExtensionByName(name); } + @Override public ExtensionRegistry.ExtensionInfo findExtensionByNumber( - ExtensionRegistry registry, Descriptors.Descriptor containingType, - int fieldNumber) { + ExtensionRegistry registry, Descriptors.Descriptor containingType, int fieldNumber) { return registry.findImmutableExtensionByNumber(containingType, fieldNumber); } - public Object parseGroup(CodedInputStream input, + @Override + public Object parseGroup( + CodedInputStream input, ExtensionRegistryLite extensionRegistry, - Descriptors.FieldDescriptor field, Message defaultInstance) + Descriptors.FieldDescriptor field, + Message defaultInstance) throws IOException { Message.Builder subBuilder; // When default instance is not null. The field is an extension field. @@ -463,9 +473,12 @@ class MessageReflection { return subBuilder.buildPartial(); } - public Object parseMessage(CodedInputStream input, + @Override + public Object parseMessage( + CodedInputStream input, ExtensionRegistryLite extensionRegistry, - Descriptors.FieldDescriptor field, Message defaultInstance) + Descriptors.FieldDescriptor field, + Message defaultInstance) throws IOException { Message.Builder subBuilder; // When default instance is not null. The field is an extension field. @@ -484,9 +497,12 @@ class MessageReflection { return subBuilder.buildPartial(); } - public Object parseMessageFromBytes(ByteString bytes, + @Override + public Object parseMessageFromBytes( + ByteString bytes, ExtensionRegistryLite extensionRegistry, - Descriptors.FieldDescriptor field, Message defaultInstance) + Descriptors.FieldDescriptor field, + Message defaultInstance) throws IOException { Message.Builder subBuilder; // When default instance is not null. The field is an extension field. @@ -505,8 +521,9 @@ class MessageReflection { return subBuilder.buildPartial(); } - public MergeTarget newMergeTargetForField(Descriptors.FieldDescriptor field, - Message defaultInstance) { + @Override + public MergeTarget newMergeTargetForField( + Descriptors.FieldDescriptor field, Message defaultInstance) { if (defaultInstance != null) { return new BuilderAdapter( defaultInstance.newBuilderForType()); @@ -515,8 +532,8 @@ class MessageReflection { } } - public WireFormat.Utf8Validation - getUtf8Validation(Descriptors.FieldDescriptor descriptor) { + @Override + public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor descriptor) { if (descriptor.needsUtf8Check()) { return WireFormat.Utf8Validation.STRICT; } @@ -528,9 +545,11 @@ class MessageReflection { return WireFormat.Utf8Validation.LOOSE; } + @Override public Object finish() { return builder.buildPartial(); } + } @@ -542,38 +561,43 @@ class MessageReflection { this.extensions = extensions; } + @Override public Descriptors.Descriptor getDescriptorForType() { throw new UnsupportedOperationException( "getDescriptorForType() called on FieldSet object"); } + @Override public Object getField(Descriptors.FieldDescriptor field) { return extensions.getField(field); } + @Override public boolean hasField(Descriptors.FieldDescriptor field) { return extensions.hasField(field); } - public MergeTarget setField(Descriptors.FieldDescriptor field, - Object value) { + @Override + public MergeTarget setField(Descriptors.FieldDescriptor field, Object value) { extensions.setField(field, value); return this; } + @Override public MergeTarget clearField(Descriptors.FieldDescriptor field) { extensions.clearField(field); return this; } + @Override public MergeTarget setRepeatedField( Descriptors.FieldDescriptor field, int index, Object value) { extensions.setRepeatedField(field, index, value); return this; } - public MergeTarget addRepeatedField( - Descriptors.FieldDescriptor field, Object value) { + @Override + public MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, Object value) { extensions.addRepeatedField(field, value); return this; } @@ -594,25 +618,31 @@ class MessageReflection { return null; } + @Override public ContainerType getContainerType() { return ContainerType.EXTENSION_SET; } + @Override public ExtensionRegistry.ExtensionInfo findExtensionByName( ExtensionRegistry registry, String name) { return registry.findImmutableExtensionByName(name); } + @Override public ExtensionRegistry.ExtensionInfo findExtensionByNumber( - ExtensionRegistry registry, Descriptors.Descriptor containingType, - int fieldNumber) { + ExtensionRegistry registry, Descriptors.Descriptor containingType, int fieldNumber) { return registry.findImmutableExtensionByNumber(containingType, fieldNumber); } - public Object parseGroup(CodedInputStream input, - ExtensionRegistryLite registry, Descriptors.FieldDescriptor field, - Message defaultInstance) throws IOException { + @Override + public Object parseGroup( + CodedInputStream input, + ExtensionRegistryLite registry, + Descriptors.FieldDescriptor field, + Message defaultInstance) + throws IOException { Message.Builder subBuilder = defaultInstance.newBuilderForType(); if (!field.isRepeated()) { @@ -625,9 +655,13 @@ class MessageReflection { return subBuilder.buildPartial(); } - public Object parseMessage(CodedInputStream input, - ExtensionRegistryLite registry, Descriptors.FieldDescriptor field, - Message defaultInstance) throws IOException { + @Override + public Object parseMessage( + CodedInputStream input, + ExtensionRegistryLite registry, + Descriptors.FieldDescriptor field, + Message defaultInstance) + throws IOException { Message.Builder subBuilder = defaultInstance.newBuilderForType(); if (!field.isRepeated()) { @@ -640,9 +674,13 @@ class MessageReflection { return subBuilder.buildPartial(); } - public Object parseMessageFromBytes(ByteString bytes, - ExtensionRegistryLite registry, Descriptors.FieldDescriptor field, - Message defaultInstance) throws IOException { + @Override + public Object parseMessageFromBytes( + ByteString bytes, + ExtensionRegistryLite registry, + Descriptors.FieldDescriptor field, + Message defaultInstance) + throws IOException { Message.Builder subBuilder = defaultInstance.newBuilderForType(); if (!field.isRepeated()) { Message originalMessage = (Message) getField(field); @@ -654,14 +692,15 @@ class MessageReflection { return subBuilder.buildPartial(); } + @Override public MergeTarget newMergeTargetForField( Descriptors.FieldDescriptor descriptor, Message defaultInstance) { throw new UnsupportedOperationException( "newMergeTargetForField() called on FieldSet object"); } - public WireFormat.Utf8Validation - getUtf8Validation(Descriptors.FieldDescriptor descriptor) { + @Override + public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor descriptor) { if (descriptor.needsUtf8Check()) { return WireFormat.Utf8Validation.STRICT; } @@ -669,10 +708,12 @@ class MessageReflection { return WireFormat.Utf8Validation.LOOSE; } + @Override public Object finish() { throw new UnsupportedOperationException( "finish() called on FieldSet object"); } + } /** 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 d2f82ac5..81255ec2 100644 --- a/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java @@ -38,7 +38,7 @@ import java.util.List; /** * Implements {@link ProtobufList} for non-primitive and {@link String} types. */ -class ProtobufArrayList<E> extends AbstractProtobufList<E> { +final class ProtobufArrayList<E> extends AbstractProtobufList<E> { private static final ProtobufArrayList<Object> EMPTY_LIST = new ProtobufArrayList<Object>(); static { @@ -51,17 +51,23 @@ class ProtobufArrayList<E> extends AbstractProtobufList<E> { } private final List<E> list; - + ProtobufArrayList() { - list = new ArrayList<E>(); + this(new ArrayList<E>(DEFAULT_CAPACITY)); } - ProtobufArrayList(List<E> toCopy) { - list = new ArrayList<E>(toCopy); + private ProtobufArrayList(List<E> list) { + this.list = list; } - - ProtobufArrayList(int capacity) { - list = new ArrayList<E>(capacity); + + @Override + public ProtobufArrayList<E> mutableCopyWithCapacity(int capacity) { + if (capacity < size()) { + throw new IllegalArgumentException(); + } + List<E> newList = new ArrayList<E>(capacity); + newList.addAll(list); + return new ProtobufArrayList<E>(newList); } @Override 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 0c8df989..a596d301 100644 --- a/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java +++ b/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java @@ -42,6 +42,7 @@ public interface ProtocolMessageEnum extends Internal.EnumLite { /** * Return the value's numeric value as defined in the .proto file. */ + @Override int getNumber(); /** 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 f91cdbce..29f567dc 100644 --- a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java +++ b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java @@ -579,7 +579,7 @@ public class RepeatedFieldBuilder } } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public void markDirty() { onChanged(); } @@ -621,10 +621,12 @@ public class RepeatedFieldBuilder this.builder = builder; } + @Override public int size() { return this.builder.getCount(); } + @Override public MType get(int index) { return builder.getMessage(index); } @@ -654,10 +656,12 @@ public class RepeatedFieldBuilder this.builder = builder; } + @Override public int size() { return this.builder.getCount(); } + @Override public BType get(int index) { return builder.getBuilder(index); } @@ -687,10 +691,12 @@ public class RepeatedFieldBuilder this.builder = builder; } + @Override public int size() { return this.builder.getCount(); } + @Override public IType get(int index) { return builder.getMessageOrBuilder(index); } 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 694b8d13..f7d555ae 100644 --- a/java/core/src/main/java/com/google/protobuf/RpcUtil.java +++ b/java/core/src/main/java/com/google/protobuf/RpcUtil.java @@ -71,6 +71,7 @@ public final class RpcUtil { final Class<Type> originalClass, final Type defaultInstance) { return new RpcCallback<Message>() { + @Override public void run(final Message parameter) { Type typedParameter; try { @@ -107,8 +108,9 @@ public final class RpcUtil { return new RpcCallback<ParameterType>() { private boolean alreadyCalled = false; + @Override public void run(final ParameterType parameter) { - synchronized(this) { + synchronized (this) { if (alreadyCalled) { throw new AlreadyCalledException(); } 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 aba65e32..941b5def 100644 --- a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java +++ b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java @@ -234,7 +234,7 @@ public class SingleFieldBuilder } } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public void markDirty() { onChanged(); } diff --git a/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java b/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java index dff19328..409fec10 100644 --- a/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java +++ b/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java @@ -411,22 +411,22 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> { this.value = value; } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public K getKey() { return key; } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public V getValue() { return value; } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public int compareTo(Entry other) { return getKey().compareTo(other.getKey()); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public V setValue(V newValue) { checkMutable(); final V oldValue = this.value; @@ -535,13 +535,13 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> { private boolean nextCalledBeforeRemove; private Iterator<Map.Entry<K, V>> lazyOverflowIterator; - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public boolean hasNext() { return (pos + 1) < entryList.size() || getOverflowIterator().hasNext(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public Map.Entry<K, V> next() { nextCalledBeforeRemove = true; // Always increment pos so that we know whether the last returned value @@ -552,7 +552,7 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> { return getOverflowIterator().next(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public void remove() { if (!nextCalledBeforeRemove) { throw new IllegalStateException("remove() was called before next()"); @@ -588,31 +588,83 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> { */ private static class EmptySet { - private static final Iterator<Object> ITERATOR = new Iterator<Object>() { - //@Override (Java 1.6 override semantics, but we must support 1.5) - public boolean hasNext() { - return false; - } - //@Override (Java 1.6 override semantics, but we must support 1.5) - public Object next() { - throw new NoSuchElementException(); - } - //@Override (Java 1.6 override semantics, but we must support 1.5) - public void remove() { - throw new UnsupportedOperationException(); - } - }; + private static final Iterator<Object> ITERATOR = + new Iterator<Object>() { + @Override + public boolean hasNext() { + return false; + } + @Override + public Object next() { + throw new NoSuchElementException(); + } + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; - private static final Iterable<Object> ITERABLE = new Iterable<Object>() { - //@Override (Java 1.6 override semantics, but we must support 1.5) - public Iterator<Object> iterator() { - return ITERATOR; - } - }; + private static final Iterable<Object> ITERABLE = + new Iterable<Object>() { + @Override + public Iterator<Object> iterator() { + return ITERATOR; + } + }; @SuppressWarnings("unchecked") static <T> Iterable<T> iterable() { return (Iterable<T>) ITERABLE; } } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (!(o instanceof SmallSortedMap)) { + return super.equals(o); + } + + SmallSortedMap<?, ?> other = (SmallSortedMap<?, ?>) o; + final int size = size(); + if (size != other.size()) { + return false; + } + + // Best effort try to avoid allocating an entry set. + final int numArrayEntries = getNumArrayEntries(); + if (numArrayEntries != other.getNumArrayEntries()) { + return entrySet().equals(other.entrySet()); + } + + for (int i = 0; i < numArrayEntries; i++) { + if (!getArrayEntryAt(i).equals(other.getArrayEntryAt(i))) { + return false; + } + } + + if (numArrayEntries != size) { + return overflowEntries.equals(other.overflowEntries); + } + + + return true; + } + + @Override + public int hashCode() { + int h = 0; + final int listSize = getNumArrayEntries(); + for (int i = 0; i < listSize; i++) { + h += entryList.get(i).hashCode(); + } + // Avoid the iterator allocation if possible. + if (getNumOverflowEntries() > 0) { + h += overflowEntries.hashCode(); + } + return h; + } } 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 edf114fa..c1c328fc 100644 --- a/java/core/src/main/java/com/google/protobuf/TextFormat.java +++ b/java/core/src/main/java/com/google/protobuf/TextFormat.java @@ -965,11 +965,13 @@ public final class TextFormat { */ public boolean consumeBoolean() throws ParseException { if (currentToken.equals("true") + || currentToken.equals("True") || currentToken.equals("t") || currentToken.equals("1")) { nextToken(); return true; } else if (currentToken.equals("false") + || currentToken.equals("False") || currentToken.equals("f") || currentToken.equals("0")) { nextToken(); 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 7cd2250e..c906420d 100644 --- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java +++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java @@ -76,6 +76,7 @@ public final class UnknownFieldSet implements MessageLite { public static UnknownFieldSet getDefaultInstance() { return defaultInstance; } + @Override public UnknownFieldSet getDefaultInstanceForType() { return defaultInstance; } @@ -126,6 +127,7 @@ public final class UnknownFieldSet implements MessageLite { } /** Serializes the set and writes it to {@code output}. */ + @Override public void writeTo(final CodedOutputStream output) throws IOException { for (final Map.Entry<Integer, Field> entry : fields.entrySet()) { entry.getValue().writeTo(entry.getKey(), output); @@ -146,6 +148,7 @@ public final class UnknownFieldSet implements MessageLite { * 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 = @@ -163,6 +166,7 @@ public final class UnknownFieldSet implements MessageLite { * 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() { try { final byte[] result = new byte[getSerializedSize()]; @@ -181,12 +185,14 @@ public final class UnknownFieldSet implements MessageLite { * 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 { final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); writeTo(codedOutput); codedOutput.flush(); } + @Override public void writeDelimitedTo(OutputStream output) throws IOException { final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); codedOutput.writeRawVarint32(getSerializedSize()); @@ -195,6 +201,7 @@ public final class UnknownFieldSet implements MessageLite { } /** Get the number of bytes required to encode this set. */ + @Override public int getSerializedSize() { int result = 0; for (final Map.Entry<Integer, Field> entry : fields.entrySet()) { @@ -228,6 +235,7 @@ public final class UnknownFieldSet implements MessageLite { return result; } + @Override public boolean isInitialized() { // UnknownFieldSets do not have required fields, so they are always // initialized. @@ -258,10 +266,12 @@ public final class UnknownFieldSet implements MessageLite { return newBuilder().mergeFrom(input).build(); } + @Override public Builder newBuilderForType() { return newBuilder(); } + @Override public Builder toBuilder() { return newBuilder().mergeFrom(this); } @@ -329,6 +339,7 @@ public final class UnknownFieldSet implements MessageLite { * in undefined behavior and can cause a {@code NullPointerException} to be * thrown. */ + @Override public UnknownFieldSet build() { getFieldBuilder(0); // Force lastField to be built. final UnknownFieldSet result; @@ -341,6 +352,7 @@ public final class UnknownFieldSet implements MessageLite { return result; } + @Override public UnknownFieldSet buildPartial() { // No required fields, so this is the same as build(). return build(); @@ -353,6 +365,7 @@ public final class UnknownFieldSet implements MessageLite { new UnknownFieldSet(fields)); } + @Override public UnknownFieldSet getDefaultInstanceForType() { return UnknownFieldSet.getDefaultInstance(); } @@ -364,6 +377,7 @@ public final class UnknownFieldSet implements MessageLite { } /** Reset the builder to an empty set. */ + @Override public Builder clear() { reinitialize(); return this; @@ -487,6 +501,7 @@ public final class UnknownFieldSet implements MessageLite { * 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) { final int tag = input.readTag(); @@ -536,8 +551,8 @@ public final class UnknownFieldSet implements MessageLite { * set being built. This is just a small wrapper around * {@link #mergeFrom(CodedInputStream)}. */ - public Builder mergeFrom(final ByteString data) - throws InvalidProtocolBufferException { + @Override + public Builder mergeFrom(final ByteString data) throws InvalidProtocolBufferException { try { final CodedInputStream input = data.newCodedInput(); mergeFrom(input); @@ -557,8 +572,8 @@ public final class UnknownFieldSet implements MessageLite { * set being built. This is just a small wrapper around * {@link #mergeFrom(CodedInputStream)}. */ - public Builder mergeFrom(final byte[] data) - throws InvalidProtocolBufferException { + @Override + public Builder mergeFrom(final byte[] data) throws InvalidProtocolBufferException { try { final CodedInputStream input = CodedInputStream.newInstance(data); mergeFrom(input); @@ -578,6 +593,7 @@ public final class UnknownFieldSet implements MessageLite { * set being built. This is just a small wrapper around * {@link #mergeFrom(CodedInputStream)}. */ + @Override public Builder mergeFrom(final InputStream input) throws IOException { final CodedInputStream codedInput = CodedInputStream.newInstance(input); mergeFrom(codedInput); @@ -585,8 +601,8 @@ public final class UnknownFieldSet implements MessageLite { return this; } - public boolean mergeDelimitedFrom(InputStream input) - throws IOException { + @Override + public boolean mergeDelimitedFrom(InputStream input) throws IOException { final int firstByte = input.read(); if (firstByte == -1) { return false; @@ -597,30 +613,29 @@ public final class UnknownFieldSet implements MessageLite { return true; } - public boolean mergeDelimitedFrom( - InputStream input, - ExtensionRegistryLite extensionRegistry) throws IOException { + @Override + public boolean mergeDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry) + throws IOException { // UnknownFieldSet has no extensions. return mergeDelimitedFrom(input); } - public Builder mergeFrom( - CodedInputStream input, - ExtensionRegistryLite extensionRegistry) throws IOException { + @Override + public Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry) + throws IOException { // UnknownFieldSet has no extensions. return mergeFrom(input); } - public Builder mergeFrom( - ByteString data, - ExtensionRegistryLite extensionRegistry) + @Override + public Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { // UnknownFieldSet has no extensions. return mergeFrom(data); } - public Builder mergeFrom(byte[] data, int off, int len) - throws InvalidProtocolBufferException { + @Override + public Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException { try { final CodedInputStream input = CodedInputStream.newInstance(data, off, len); @@ -636,29 +651,37 @@ public final class UnknownFieldSet implements MessageLite { } } - public Builder mergeFrom( - byte[] data, - ExtensionRegistryLite extensionRegistry) + @Override + public Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { // UnknownFieldSet has no extensions. return mergeFrom(data); } - public Builder mergeFrom( - byte[] data, int off, int len, - ExtensionRegistryLite extensionRegistry) + @Override + public Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { // UnknownFieldSet has no extensions. return mergeFrom(data, off, len); } - public Builder mergeFrom( - InputStream input, - ExtensionRegistryLite extensionRegistry) throws IOException { + @Override + public Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry) + throws IOException { // UnknownFieldSet has no extensions. return mergeFrom(input); } + @Override + public Builder mergeFrom(MessageLite m) { + if (m instanceof UnknownFieldSet) { + return mergeFrom((UnknownFieldSet) m); + } + throw new IllegalArgumentException( + "mergeFrom(MessageLite) can only merge messages of the same type."); + } + + @Override public boolean isInitialized() { // UnknownFieldSets do not have required fields, so they are always // initialized. @@ -987,6 +1010,7 @@ public final class UnknownFieldSet implements MessageLite { * Parser to implement MessageLite interface. */ public static final class Parser extends AbstractParser<UnknownFieldSet> { + @Override public UnknownFieldSet parsePartialFrom( CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { @@ -1004,6 +1028,7 @@ public final class UnknownFieldSet implements MessageLite { } 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/UnmodifiableLazyStringList.java b/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java index 5257c5a2..30e87911 100644 --- a/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java +++ b/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java @@ -68,42 +68,42 @@ public class UnmodifiableLazyStringList extends AbstractList<String> return list.size(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public ByteString getByteString(int index) { return list.getByteString(index); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public void add(ByteString element) { throw new UnsupportedOperationException(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public void set(int index, ByteString element) { throw new UnsupportedOperationException(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public boolean addAllByteString(Collection<? extends ByteString> element) { throw new UnsupportedOperationException(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public byte[] getByteArray(int index) { return list.getByteArray(index); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public void add(byte[] element) { throw new UnsupportedOperationException(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public void set(int index, byte[] element) { throw new UnsupportedOperationException(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public boolean addAllByteArray(Collection<byte[]> element) { throw new UnsupportedOperationException(); } @@ -113,47 +113,47 @@ public class UnmodifiableLazyStringList extends AbstractList<String> return new ListIterator<String>() { ListIterator<String> iter = list.listIterator(index); - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public boolean hasNext() { return iter.hasNext(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public String next() { return iter.next(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public boolean hasPrevious() { return iter.hasPrevious(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public String previous() { return iter.previous(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public int nextIndex() { return iter.nextIndex(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public int previousIndex() { return iter.previousIndex(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public void remove() { throw new UnsupportedOperationException(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public void set(String o) { throw new UnsupportedOperationException(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public void add(String o) { throw new UnsupportedOperationException(); } @@ -165,45 +165,45 @@ public class UnmodifiableLazyStringList extends AbstractList<String> return new Iterator<String>() { Iterator<String> iter = list.iterator(); - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public boolean hasNext() { return iter.hasNext(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public String next() { return iter.next(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public void remove() { throw new UnsupportedOperationException(); } }; } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public List<?> getUnderlyingElements() { // The returned value is already unmodifiable. return list.getUnderlyingElements(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public void mergeFrom(LazyStringList other) { throw new UnsupportedOperationException(); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public List<byte[]> asByteArrayList() { return Collections.unmodifiableList(list.asByteArrayList()); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public List<ByteString> asByteStringList() { return Collections.unmodifiableList(list.asByteStringList()); } - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public LazyStringList getUnmodifiableView() { return this; } 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 8dbe1ae3..6a58b081 100644 --- a/java/core/src/main/java/com/google/protobuf/WireFormat.java +++ b/java/core/src/main/java/com/google/protobuf/WireFormat.java @@ -116,16 +116,24 @@ public final class WireFormat { FIXED32 (JavaType.INT , WIRETYPE_FIXED32 ), BOOL (JavaType.BOOLEAN , WIRETYPE_VARINT ), STRING (JavaType.STRING , WIRETYPE_LENGTH_DELIMITED) { - public boolean isPackable() { return false; } + @Override + public boolean isPackable() { + return false; } }, GROUP (JavaType.MESSAGE , WIRETYPE_START_GROUP ) { - public boolean isPackable() { return false; } + @Override + public boolean isPackable() { + return false; } }, MESSAGE (JavaType.MESSAGE , WIRETYPE_LENGTH_DELIMITED) { - public boolean isPackable() { return false; } + @Override + public boolean isPackable() { + return false; } }, BYTES (JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED) { - public boolean isPackable() { return false; } + @Override + public boolean isPackable() { + return false; } }, UINT32 (JavaType.INT , WIRETYPE_VARINT ), ENUM (JavaType.ENUM , WIRETYPE_VARINT ), @@ -170,18 +178,21 @@ public final class WireFormat { enum Utf8Validation { /** Eagerly parses to String; silently accepts invalid UTF8 bytes. */ LOOSE { + @Override Object readString(CodedInputStream input) throws IOException { return input.readString(); } }, /** Eagerly parses to String; throws an IOException on invalid bytes. */ STRICT { + @Override Object readString(CodedInputStream input) throws IOException { return input.readStringRequireUtf8(); } }, /** Keep data as ByteString; validation/conversion to String is lazy. */ LAZY { + @Override Object readString(CodedInputStream input) throws IOException { return input.readBytes(); } 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 1e57b647..7dc9fc15 100644 --- a/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java +++ b/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java @@ -64,35 +64,44 @@ public class AbstractMessageTest extends TestCase { this.wrappedMessage = wrappedMessage; } + @Override public Descriptors.Descriptor getDescriptorForType() { return wrappedMessage.getDescriptorForType(); } + @Override public AbstractMessageWrapper getDefaultInstanceForType() { return new AbstractMessageWrapper( wrappedMessage.getDefaultInstanceForType()); } + @Override public Map<Descriptors.FieldDescriptor, Object> 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); } - public Object getRepeatedField( - Descriptors.FieldDescriptor field, int index) { + @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()); } @@ -104,65 +113,80 @@ public class AbstractMessageTest extends TestCase { this.wrappedBuilder = wrappedBuilder; } + @Override 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()); } + @Override public Map<Descriptors.FieldDescriptor, Object> 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); } - public Object getRepeatedField( - Descriptors.FieldDescriptor field, int index) { + @Override + public Object getRepeatedField(Descriptors.FieldDescriptor field, int index) { return wrappedBuilder.getRepeatedField(field, index); } - public Builder setRepeatedField(Descriptors.FieldDescriptor field, - int index, Object value) { + @Override + public Builder setRepeatedField(Descriptors.FieldDescriptor field, int index, Object value) { wrappedBuilder.setRepeatedField(field, index, value); return this; } - public Builder addRepeatedField( - Descriptors.FieldDescriptor field, Object value) { + @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; @@ -172,6 +196,7 @@ public class AbstractMessageTest extends TestCase { return wrappedBuilder.getFieldBuilder(field); } } + @Override public Parser<? extends Message> getParserForType() { return wrappedMessage.getParserForType(); } 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 b8ad1fe4..24b96c60 100644 --- a/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java @@ -73,20 +73,6 @@ public class BooleanArrayListTest extends TestCase { assertImmutable(list); } - public void testCopyConstructor() { - BooleanArrayList copy = new BooleanArrayList(TERTIARY_LIST); - assertEquals(TERTIARY_LIST, copy); - - copy = new BooleanArrayList(BooleanArrayList.emptyList()); - assertEquals(BooleanArrayList.emptyList(), copy); - - copy = new BooleanArrayList(asList(false, false, true)); - assertEquals(asList(false, false, true), copy); - - copy = new BooleanArrayList(Collections.<Boolean>emptyList()); - assertEquals(BooleanArrayList.emptyList(), copy); - } - public void testModificationWithIteration() { list.addAll(asList(true, false, false, true)); Iterator<Boolean> iterator = list.iterator(); 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 a1d6f1be..ca940ced 100644 --- a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java +++ b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java @@ -81,10 +81,12 @@ public class CodedInputStreamTest extends TestCase { this.blockSize = blockSize; } + @Override public int read(byte[] b) throws IOException { return super.read(b, 0, Math.min(b.length, blockSize)); } + @Override public int read(byte[] b, int off, int len) throws IOException { return super.read(b, off, Math.min(len, blockSize)); } 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 6018ea55..33aa4357 100644 --- a/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java +++ b/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java @@ -30,6 +30,7 @@ package com.google.protobuf; +import com.google.protobuf.CodedOutputStream.OutOfSpaceException; import protobuf_unittest.UnittestProto.SparseEnumMessage; import protobuf_unittest.UnittestProto.TestAllTypes; import protobuf_unittest.UnittestProto.TestPackedTypes; @@ -50,118 +51,180 @@ import java.util.List; * @author kenton@google.com Kenton Varda */ public class CodedOutputStreamTest extends TestCase { - /** - * 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 byte[] bytes(int... bytesAsInts) { - byte[] bytes = new byte[bytesAsInts.length]; - for (int i = 0; i < bytesAsInts.length; i++) { - bytes[i] = (byte) bytesAsInts[i]; - } - return bytes; + private interface Coder { + CodedOutputStream stream(); + + byte[] toByteArray(); + + OutputType getOutputType(); } - /** Arrays.asList() does not work with arrays of primitives. :( */ - private List<Byte> toList(byte[] bytes) { - List<Byte> result = new ArrayList<Byte>(); - for (byte b : bytes) { - result.add(b); + private static final class OutputStreamCoder implements Coder { + private final CodedOutputStream stream; + private final ByteArrayOutputStream output; + + OutputStreamCoder(int size) { + output = new ByteArrayOutputStream(); + stream = CodedOutputStream.newInstance(output, size); + } + + @Override + public CodedOutputStream stream() { + return stream; + } + + @Override + public byte[] toByteArray() { + return output.toByteArray(); + } + + @Override + public OutputType getOutputType() { + return OutputType.STREAM; } - return result; } - private void assertEqualBytes(byte[] a, byte[] b) { - assertEquals(toList(a), toList(b)); + private static final class ArrayCoder implements Coder { + private final CodedOutputStream stream; + private final byte[] bytes; + + ArrayCoder(int size) { + bytes = new byte[size]; + stream = CodedOutputStream.newInstance(bytes); + } + + @Override + public CodedOutputStream stream() { + return stream; + } + + @Override + public byte[] toByteArray() { + return Arrays.copyOf(bytes, stream.getTotalBytesWritten()); + } + + @Override + public OutputType getOutputType() { + return OutputType.ARRAY; + } } - /** - * Writes the given value using writeRawVarint32() and writeRawVarint64() and - * checks that the result matches the given bytes. - */ - private void assertWriteVarint(byte[] data, long value) throws Exception { - // Only test 32-bit write if the value fits into an int. - if (value == (int) value) { - ByteArrayOutputStream rawOutput = new ByteArrayOutputStream(); - CodedOutputStream output = CodedOutputStream.newInstance(rawOutput); - output.writeRawVarint32((int) value); - output.flush(); - assertEqualBytes(data, rawOutput.toByteArray()); + private static final class NioHeapCoder implements Coder { + private final CodedOutputStream stream; + private final ByteBuffer buffer; + private final int initialPosition; - // Also try computing size. - assertEquals(data.length, - CodedOutputStream.computeRawVarint32Size((int) value)); + NioHeapCoder(int size) { + this(size, 0); } - { - ByteArrayOutputStream rawOutput = new ByteArrayOutputStream(); - CodedOutputStream output = CodedOutputStream.newInstance(rawOutput); - output.writeRawVarint64(value); - output.flush(); - assertEqualBytes(data, rawOutput.toByteArray()); + NioHeapCoder(int size, int initialPosition) { + this.initialPosition = initialPosition; + buffer = ByteBuffer.allocate(size); + buffer.position(initialPosition); + stream = CodedOutputStream.newInstance(buffer); + } - // Also try computing size. - assertEquals(data.length, - CodedOutputStream.computeRawVarint64Size(value)); + @Override + public CodedOutputStream stream() { + return stream; } - // Try different block sizes. - for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { - // Only test 32-bit write if the value fits into an int. - if (value == (int) value) { - ByteArrayOutputStream rawOutput = new ByteArrayOutputStream(); - CodedOutputStream output = - CodedOutputStream.newInstance(rawOutput, blockSize); - output.writeRawVarint32((int) value); - output.flush(); - assertEqualBytes(data, rawOutput.toByteArray()); - } + @Override + public byte[] toByteArray() { + ByteBuffer dup = buffer.duplicate(); + dup.position(initialPosition); + dup.limit(buffer.position()); - { - ByteArrayOutputStream rawOutput = new ByteArrayOutputStream(); - CodedOutputStream output = - CodedOutputStream.newInstance(rawOutput, blockSize); - output.writeRawVarint64(value); - output.flush(); - assertEqualBytes(data, rawOutput.toByteArray()); - } + byte[] bytes = new byte[dup.remaining()]; + dup.get(bytes); + return bytes; + } + + @Override + public OutputType getOutputType() { + return OutputType.NIO_HEAP; } } - private void assertVarintRoundTrip(long value) throws Exception { - { - ByteArrayOutputStream rawOutput = new ByteArrayOutputStream(); - CodedOutputStream output = CodedOutputStream.newInstance(rawOutput); - output.writeRawVarint64(value); - output.flush(); - byte[] bytes = rawOutput.toByteArray(); - assertEquals(bytes.length, CodedOutputStream.computeRawVarint64Size(value)); - CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(bytes)); - assertEquals(value, input.readRawVarint64()); + private static final class NioDirectCoder implements Coder { + private final int initialPosition; + private final CodedOutputStream stream; + private final ByteBuffer buffer; + + NioDirectCoder(int size) { + this(size, 0); } - if (value == (int) value) { - ByteArrayOutputStream rawOutput = new ByteArrayOutputStream(); - CodedOutputStream output = CodedOutputStream.newInstance(rawOutput); - output.writeRawVarint32((int) value); - output.flush(); - byte[] bytes = rawOutput.toByteArray(); - assertEquals(bytes.length, CodedOutputStream.computeRawVarint32Size((int) value)); - CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(bytes)); - assertEquals(value, input.readRawVarint32()); + NioDirectCoder(int size, int initialPosition) { + this.initialPosition = initialPosition; + buffer = ByteBuffer.allocateDirect(size); + buffer.position(initialPosition); + stream = CodedOutputStream.newInstance(buffer); + } + + @Override + public CodedOutputStream stream() { + return stream; + } + + @Override + public byte[] toByteArray() { + ByteBuffer dup = buffer.duplicate(); + dup.position(initialPosition); + dup.limit(buffer.position()); + + byte[] bytes = new byte[dup.remaining()]; + dup.get(bytes); + return bytes; + } + + @Override + public OutputType getOutputType() { + return OutputType.NIO_DIRECT; } } + private enum OutputType { + ARRAY() { + @Override + Coder newCoder(int size) { + return new ArrayCoder(size); + } + }, + NIO_HEAP() { + @Override + Coder newCoder(int size) { + return new NioHeapCoder(size); + } + }, + NIO_DIRECT() { + @Override + Coder newCoder(int size) { + return new NioDirectCoder(size); + } + }, + STREAM() { + @Override + Coder newCoder(int size) { + return new OutputStreamCoder(size); + } + }; + + abstract Coder newCoder(int size); + } + /** Checks that invariants are maintained for varint round trip input and output. */ public void testVarintRoundTrips() throws Exception { - assertVarintRoundTrip(0L); - for (int bits = 0; bits < 64; bits++) { - long value = 1L << bits; - assertVarintRoundTrip(value); - assertVarintRoundTrip(value + 1); - assertVarintRoundTrip(value - 1); - assertVarintRoundTrip(-value); + for (OutputType outputType : OutputType.values()) { + assertVarintRoundTrip(outputType, 0L); + for (int bits = 0; bits < 64; bits++) { + long value = 1L << bits; + assertVarintRoundTrip(outputType, value); + assertVarintRoundTrip(outputType, value + 1); + assertVarintRoundTrip(outputType, value - 1); + assertVarintRoundTrip(outputType, -value); + } } } @@ -173,70 +236,25 @@ public class CodedOutputStreamTest extends TestCase { // 14882 assertWriteVarint(bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7)); // 2961488830 - assertWriteVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b), - (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | - (0x0bL << 28)); + assertWriteVarint( + bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b), + (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | (0x0bL << 28)); // 64-bit // 7256456126 - assertWriteVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b), - (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | - (0x1bL << 28)); + assertWriteVarint( + bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b), + (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | (0x1bL << 28)); // 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)); + 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)); // 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)); - } - - /** - * Parses the given bytes using writeRawLittleEndian32() and checks - * that the result matches the given value. - */ - private void assertWriteLittleEndian32(byte[] data, int value) - throws Exception { - ByteArrayOutputStream rawOutput = new ByteArrayOutputStream(); - CodedOutputStream output = CodedOutputStream.newInstance(rawOutput); - output.writeRawLittleEndian32(value); - output.flush(); - assertEqualBytes(data, rawOutput.toByteArray()); - - // Try different block sizes. - for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { - rawOutput = new ByteArrayOutputStream(); - output = CodedOutputStream.newInstance(rawOutput, blockSize); - output.writeRawLittleEndian32(value); - output.flush(); - assertEqualBytes(data, rawOutput.toByteArray()); - } - } - - /** - * Parses the given bytes using writeRawLittleEndian64() and checks - * that the result matches the given value. - */ - private void assertWriteLittleEndian64(byte[] data, long value) - throws Exception { - ByteArrayOutputStream rawOutput = new ByteArrayOutputStream(); - CodedOutputStream output = CodedOutputStream.newInstance(rawOutput); - output.writeRawLittleEndian64(value); - output.flush(); - assertEqualBytes(data, rawOutput.toByteArray()); - - // Try different block sizes. - for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { - rawOutput = new ByteArrayOutputStream(); - output = CodedOutputStream.newInstance(rawOutput, blockSize); - output.writeRawLittleEndian64(value); - output.flush(); - assertEqualBytes(data, rawOutput.toByteArray()); - } + 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)); } /** Tests writeRawLittleEndian32() and writeRawLittleEndian64(). */ @@ -245,141 +263,138 @@ public class CodedOutputStreamTest extends TestCase { assertWriteLittleEndian32(bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0); assertWriteLittleEndian64( - bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12), - 0x123456789abcdef0L); + bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12), 0x123456789abcdef0L); assertWriteLittleEndian64( - bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a), - 0x9abcdef012345678L); + bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef012345678L); } /** Test encodeZigZag32() and encodeZigZag64(). */ public void testEncodeZigZag() throws Exception { - assertEquals(0, CodedOutputStream.encodeZigZag32( 0)); + assertEquals(0, CodedOutputStream.encodeZigZag32(0)); assertEquals(1, CodedOutputStream.encodeZigZag32(-1)); - assertEquals(2, CodedOutputStream.encodeZigZag32( 1)); + assertEquals(2, CodedOutputStream.encodeZigZag32(1)); assertEquals(3, CodedOutputStream.encodeZigZag32(-2)); assertEquals(0x7FFFFFFE, CodedOutputStream.encodeZigZag32(0x3FFFFFFF)); assertEquals(0x7FFFFFFF, CodedOutputStream.encodeZigZag32(0xC0000000)); assertEquals(0xFFFFFFFE, CodedOutputStream.encodeZigZag32(0x7FFFFFFF)); assertEquals(0xFFFFFFFF, CodedOutputStream.encodeZigZag32(0x80000000)); - assertEquals(0, CodedOutputStream.encodeZigZag64( 0)); + assertEquals(0, CodedOutputStream.encodeZigZag64(0)); assertEquals(1, CodedOutputStream.encodeZigZag64(-1)); - assertEquals(2, CodedOutputStream.encodeZigZag64( 1)); + assertEquals(2, CodedOutputStream.encodeZigZag64(1)); assertEquals(3, CodedOutputStream.encodeZigZag64(-2)); - assertEquals(0x000000007FFFFFFEL, - CodedOutputStream.encodeZigZag64(0x000000003FFFFFFFL)); - assertEquals(0x000000007FFFFFFFL, - CodedOutputStream.encodeZigZag64(0xFFFFFFFFC0000000L)); - assertEquals(0x00000000FFFFFFFEL, - CodedOutputStream.encodeZigZag64(0x000000007FFFFFFFL)); - assertEquals(0x00000000FFFFFFFFL, - CodedOutputStream.encodeZigZag64(0xFFFFFFFF80000000L)); - assertEquals(0xFFFFFFFFFFFFFFFEL, - CodedOutputStream.encodeZigZag64(0x7FFFFFFFFFFFFFFFL)); - assertEquals(0xFFFFFFFFFFFFFFFFL, - CodedOutputStream.encodeZigZag64(0x8000000000000000L)); + assertEquals(0x000000007FFFFFFEL, CodedOutputStream.encodeZigZag64(0x000000003FFFFFFFL)); + assertEquals(0x000000007FFFFFFFL, CodedOutputStream.encodeZigZag64(0xFFFFFFFFC0000000L)); + assertEquals(0x00000000FFFFFFFEL, CodedOutputStream.encodeZigZag64(0x000000007FFFFFFFL)); + assertEquals(0x00000000FFFFFFFFL, CodedOutputStream.encodeZigZag64(0xFFFFFFFF80000000L)); + assertEquals(0xFFFFFFFFFFFFFFFEL, CodedOutputStream.encodeZigZag64(0x7FFFFFFFFFFFFFFFL)); + assertEquals(0xFFFFFFFFFFFFFFFFL, CodedOutputStream.encodeZigZag64(0x8000000000000000L)); // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1) // were chosen semi-randomly via keyboard bashing. - assertEquals(0, - CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(0))); - assertEquals(1, - CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(1))); - assertEquals(-1, - CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-1))); - assertEquals(14927, - CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(14927))); - assertEquals(-3612, - CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-3612))); - - assertEquals(0, - CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(0))); - assertEquals(1, - CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(1))); - assertEquals(-1, - CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-1))); - assertEquals(14927, - CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(14927))); - assertEquals(-3612, - CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-3612))); - - assertEquals(856912304801416L, - CodedOutputStream.encodeZigZag64( - CodedInputStream.decodeZigZag64( - 856912304801416L))); - assertEquals(-75123905439571256L, - CodedOutputStream.encodeZigZag64( - CodedInputStream.decodeZigZag64( - -75123905439571256L))); + assertEquals(0, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(0))); + assertEquals(1, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(1))); + assertEquals(-1, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-1))); + assertEquals(14927, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(14927))); + assertEquals(-3612, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-3612))); + + assertEquals(0, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(0))); + assertEquals(1, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(1))); + assertEquals(-1, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-1))); + assertEquals(14927, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(14927))); + assertEquals(-3612, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-3612))); + + assertEquals( + 856912304801416L, + CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(856912304801416L))); + assertEquals( + -75123905439571256L, + CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-75123905439571256L))); } /** Tests writing a whole message with every field type. */ public void testWriteWholeMessage() throws Exception { + final byte[] expectedBytes = TestUtil.getGoldenMessage().toByteArray(); TestAllTypes message = TestUtil.getAllSet(); - byte[] rawBytes = message.toByteArray(); - assertEqualBytes(TestUtil.getGoldenMessage().toByteArray(), rawBytes); + for (OutputType outputType : OutputType.values()) { + Coder coder = outputType.newCoder(message.getSerializedSize()); + message.writeTo(coder.stream()); + coder.stream().flush(); + byte[] rawBytes = coder.toByteArray(); + assertEqualBytes(outputType, expectedBytes, rawBytes); + } // Try different block sizes. for (int blockSize = 1; blockSize < 256; blockSize *= 2) { - ByteArrayOutputStream rawOutput = new ByteArrayOutputStream(); - CodedOutputStream output = - CodedOutputStream.newInstance(rawOutput, blockSize); - message.writeTo(output); - output.flush(); - assertEqualBytes(rawBytes, rawOutput.toByteArray()); + Coder coder = OutputType.STREAM.newCoder(blockSize); + message.writeTo(coder.stream()); + coder.stream().flush(); + assertEqualBytes(OutputType.STREAM, expectedBytes, coder.toByteArray()); } } - /** Tests writing a whole message with every packed field type. Ensures the - * wire format of packed fields is compatible with C++. */ + /** + * 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(); TestPackedTypes message = TestUtil.getPackedSet(); - byte[] rawBytes = message.toByteArray(); - assertEqualBytes(TestUtil.getGoldenPackedFieldsMessage().toByteArray(), - rawBytes); + for (OutputType outputType : OutputType.values()) { + Coder coder = outputType.newCoder(message.getSerializedSize()); + message.writeTo(coder.stream()); + coder.stream().flush(); + byte[] rawBytes = coder.toByteArray(); + assertEqualBytes(outputType, expectedBytes, rawBytes); + } } - /** Test writing a message containing a negative enum value. This used to + /** + * 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 = SparseEnumMessage.newBuilder() - .setSparseEnum(TestSparseEnum.SPARSE_E) .build(); + SparseEnumMessage message = + SparseEnumMessage.newBuilder().setSparseEnum(TestSparseEnum.SPARSE_E).build(); assertTrue(message.getSparseEnum().getNumber() < 0); - byte[] rawBytes = message.toByteArray(); - SparseEnumMessage message2 = SparseEnumMessage.parseFrom(rawBytes); - assertEquals(TestSparseEnum.SPARSE_E, message2.getSparseEnum()); + for (OutputType outputType : OutputType.values()) { + Coder coder = outputType.newCoder(message.getSerializedSize()); + message.writeTo(coder.stream()); + coder.stream().flush(); + byte[] rawBytes = coder.toByteArray(); + SparseEnumMessage message2 = SparseEnumMessage.parseFrom(rawBytes); + assertEquals(TestSparseEnum.SPARSE_E, message2.getSparseEnum()); + } } /** Test getTotalBytesWritten() */ public void testGetTotalBytesWritten() throws Exception { - final int BUFFER_SIZE = 4 * 1024; - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(BUFFER_SIZE); - CodedOutputStream codedStream = CodedOutputStream.newInstance(outputStream); + Coder coder = OutputType.STREAM.newCoder(4 * 1024); + + // Write some some bytes (more than the buffer can hold) and verify that totalWritten + // is correct. byte[] value = "abcde".getBytes(Internal.UTF_8); for (int i = 0; i < 1024; ++i) { - codedStream.writeRawBytes(value, 0, value.length); + coder.stream().writeRawBytes(value, 0, value.length); } + assertEquals(value.length * 1024, coder.stream().getTotalBytesWritten()); + + // Now write an encoded string. String string = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"; // Ensure we take the slower fast path. - assertTrue(CodedOutputStream.computeRawVarint32Size(string.length()) - != CodedOutputStream.computeRawVarint32Size(string.length() * Utf8.MAX_BYTES_PER_CHAR)); - - codedStream.writeStringNoTag(string); + assertTrue(CodedOutputStream.computeUInt32SizeNoTag(string.length()) + != CodedOutputStream.computeUInt32SizeNoTag(string.length() * Utf8.MAX_BYTES_PER_CHAR)); + + coder.stream().writeStringNoTag(string); int stringSize = CodedOutputStream.computeStringSizeNoTag(string); - - // Make sure we have written more bytes than the buffer could hold. This is - // to make the test complete. - assertTrue(codedStream.getTotalBytesWritten() > BUFFER_SIZE); - + // Verify that the total bytes written is correct - assertEquals((value.length * 1024) + stringSize, codedStream.getTotalBytesWritten()); + assertEquals((value.length * 1024) + stringSize, coder.stream().getTotalBytesWritten()); } - + // TODO(dweis): Write a comprehensive test suite for CodedOutputStream that covers more than just // this case. public void testWriteStringNoTag_fastpath() throws Exception { @@ -390,14 +405,16 @@ public class CodedOutputStreamTest extends TestCase { string += threeBytesPer; } // These checks ensure we will tickle the slower fast path. - assertEquals(1, CodedOutputStream.computeRawVarint32Size(string.length())); + assertEquals(1, CodedOutputStream.computeUInt32SizeNoTag(string.length())); assertEquals( - 2, CodedOutputStream.computeRawVarint32Size(string.length() * Utf8.MAX_BYTES_PER_CHAR)); + 2, CodedOutputStream.computeUInt32SizeNoTag(string.length() * Utf8.MAX_BYTES_PER_CHAR)); assertEquals(bufferSize, string.length() * Utf8.MAX_BYTES_PER_CHAR); - - CodedOutputStream output = - CodedOutputStream.newInstance(ByteBuffer.allocate(bufferSize), bufferSize); - output.writeStringNoTag(string); + + for (OutputType outputType : OutputType.values()) { + Coder coder = outputType.newCoder(bufferSize + 2); + coder.stream().writeStringNoTag(string); + coder.stream().flush(); + } } public void testWriteToByteBuffer() throws Exception { @@ -464,83 +481,296 @@ public class CodedOutputStreamTest extends TestCase { byte[] destination = new byte[4]; CodedOutputStream codedStream = CodedOutputStream.newInstance(destination); codedStream.writeByteArrayNoTag(fullArray, 2, 2); - assertEqualBytes(bytes(0x02, 0x33, 0x44, 0x00), destination); + assertEqualBytes(OutputType.ARRAY, bytes(0x02, 0x33, 0x44, 0x00), destination); assertEquals(3, codedStream.getTotalBytesWritten()); } - + + public void testSerializeUtf8_MultipleSmallWrites() throws Exception { + final String source = "abcdefghijklmnopqrstuvwxyz"; + + // Generate the expected output if the source string is written 2 bytes at a time. + ByteArrayOutputStream expectedBytesStream = new ByteArrayOutputStream(); + for (int pos = 0; pos < source.length(); pos += 2) { + String substr = source.substring(pos, pos + 2); + expectedBytesStream.write(2); + expectedBytesStream.write(substr.getBytes(Internal.UTF_8)); + } + final byte[] expectedBytes = expectedBytesStream.toByteArray(); + + // For each output type, write the source string 2 bytes at a time and verify the output. + for (OutputType outputType : OutputType.values()) { + Coder coder = outputType.newCoder(expectedBytes.length); + for (int pos = 0; pos < source.length(); pos += 2) { + String substr = source.substring(pos, pos + 2); + coder.stream().writeStringNoTag(substr); + } + coder.stream().flush(); + assertEqualBytes(outputType, expectedBytes, coder.toByteArray()); + } + } + 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), + 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) - }; - + newString(Character.MIN_HIGH_SURROGATE, Character.MIN_HIGH_SURROGATE)}; + CodedOutputStream outputWithStream = CodedOutputStream.newInstance(new ByteArrayOutputStream()); CodedOutputStream outputWithArray = CodedOutputStream.newInstance(new byte[10000]); + CodedOutputStream outputWithByteBuffer = + CodedOutputStream.newInstance(ByteBuffer.allocate(10000)); for (String s : invalidStrings) { // TODO(dweis): These should all fail; instead they are corrupting data. CodedOutputStream.computeStringSizeNoTag(s); outputWithStream.writeStringNoTag(s); outputWithArray.writeStringNoTag(s); + outputWithByteBuffer.writeStringNoTag(s); } } - - private static String newString(char... chars) { - return new String(chars); + + // TODO(nathanmittler): This test can be deleted once we properly throw IOException while + // encoding invalid UTF-8 strings. + public void testSerializeInvalidUtf8FollowedByOutOfSpace() throws Exception { + final int notEnoughBytes = 4; + CodedOutputStream outputWithArray = CodedOutputStream.newInstance(new byte[notEnoughBytes]); + CodedOutputStream outputWithByteBuffer = + CodedOutputStream.newInstance(ByteBuffer.allocate(notEnoughBytes)); + + String invalidString = newString(Character.MIN_HIGH_SURROGATE, 'f', 'o', 'o', 'b', 'a', 'r'); + try { + outputWithArray.writeStringNoTag(invalidString); + fail("Expected OutOfSpaceException"); + } catch (OutOfSpaceException e) { + assertTrue(e.getCause() instanceof IndexOutOfBoundsException); + } + try { + outputWithByteBuffer.writeStringNoTag(invalidString); + fail("Expected OutOfSpaceException"); + } catch (OutOfSpaceException e) { + assertTrue(e.getCause() instanceof IndexOutOfBoundsException); + } } /** Regression test for https://github.com/google/protobuf/issues/292 */ public void testCorrectExceptionThrowWhenEncodingStringsWithoutEnoughSpace() throws Exception { String testCase = "Foooooooo"; - assertEquals(CodedOutputStream.computeRawVarint32Size(testCase.length()), - CodedOutputStream.computeRawVarint32Size(testCase.length() * 3)); + assertEquals( + CodedOutputStream.computeUInt32SizeNoTag(testCase.length()), + CodedOutputStream.computeUInt32SizeNoTag(testCase.length() * 3)); assertEquals(11, CodedOutputStream.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++) { - CodedOutputStream output = CodedOutputStream.newInstance(new byte[i]); - try { - output.writeString(1, testCase); - fail("Should have thrown an out of space exception"); - } catch (CodedOutputStream.OutOfSpaceException expected) {} + for (OutputType outputType : + new OutputType[] {OutputType.ARRAY, OutputType.NIO_HEAP, OutputType.NIO_DIRECT}) { + for (int i = 0; i < 11; i++) { + Coder coder = outputType.newCoder(i); + try { + coder.stream().writeString(1, testCase); + fail("Should have thrown an out of space exception"); + } catch (CodedOutputStream.OutOfSpaceException expected) { + } + } } } - + public void testDifferentStringLengths() 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 + 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 + for (OutputType outputType : OutputType.values()) { + for (int i : lengths) { + testEncodingOfString(outputType, 'q', i); // 1 byte per char + testEncodingOfString(outputType, '\u07FF', i); // 2 bytes per char + testEncodingOfString(outputType, '\u0981', i); // 3 bytes per char + } } } - private void testEncodingOfString(char c, int length) throws Exception { + public void testNioEncodersWithInitialOffsets() throws Exception { + String value = "abc"; + for (Coder coder : new Coder[] {new NioHeapCoder(10, 2), new NioDirectCoder(10, 2)}) { + coder.stream().writeStringNoTag(value); + coder.stream().flush(); + assertEqualBytes(coder.getOutputType(), new byte[]{3, 'a', 'b', 'c'}, coder.toByteArray()); + } + } + + /** + * 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()) { + Coder coder = outputType.newCoder(data.length); + coder.stream().writeFixed32NoTag(value); + coder.stream().flush(); + assertEqualBytes(outputType, data, coder.toByteArray()); + } + + // Try different block sizes. + for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { + Coder coder = OutputType.STREAM.newCoder(blockSize); + coder.stream().writeFixed32NoTag(value); + coder.stream().flush(); + assertEqualBytes(OutputType.STREAM, data, coder.toByteArray()); + } + } + + /** + * 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()) { + Coder coder = outputType.newCoder(data.length); + coder.stream().writeFixed64NoTag(value); + coder.stream().flush(); + assertEqualBytes(outputType, data, coder.toByteArray()); + } + + // Try different block sizes. + for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { + Coder coder = OutputType.STREAM.newCoder(blockSize); + coder.stream().writeFixed64NoTag(value); + coder.stream().flush(); + assertEqualBytes(OutputType.STREAM, data, coder.toByteArray()); + } + } + + private static String newString(char... chars) { + return new String(chars); + } + + private static void testEncodingOfString(OutputType outputType, char c, int length) + throws Exception { String fullString = fullString(c, length); - TestAllTypes testAllTypes = TestAllTypes.newBuilder() - .setOptionalString(fullString) - .build(); + TestAllTypes testAllTypes = TestAllTypes.newBuilder().setOptionalString(fullString).build(); + Coder coder = outputType.newCoder(testAllTypes.getSerializedSize()); + testAllTypes.writeTo(coder.stream()); + coder.stream().flush(); assertEquals( - fullString, TestAllTypes.parseFrom(testAllTypes.toByteArray()).getOptionalString()); + "OuputType: " + outputType, + fullString, + TestAllTypes.parseFrom(coder.toByteArray()).getOptionalString()); } - private String fullString(char c, int length) { + private static String fullString(char c, int length) { char[] result = new char[length]; Arrays.fill(result, c); return new String(result); } + + /** + * 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]; + for (int i = 0; i < bytesAsInts.length; i++) { + bytes[i] = (byte) bytesAsInts[i]; + } + return bytes; + } + + /** Arrays.asList() does not work with arrays of primitives. :( */ + private static List<Byte> toList(byte[] bytes) { + List<Byte> result = new ArrayList<Byte>(); + for (byte b : bytes) { + result.add(b); + } + return result; + } + + private static void assertEqualBytes(OutputType outputType, byte[] a, byte[] b) { + assertEquals(outputType.name(), toList(a), toList(b)); + } + + /** + * 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()) { + // Only test 32-bit write if the value fits into an int. + if (value == (int) value) { + Coder coder = outputType.newCoder(10); + coder.stream().writeUInt32NoTag((int) value); + coder.stream().flush(); + assertEqualBytes(outputType, data, coder.toByteArray()); + + // Also try computing size. + assertEquals(data.length, CodedOutputStream.computeUInt32SizeNoTag((int) value)); + } + + { + Coder coder = outputType.newCoder(10); + coder.stream().writeUInt64NoTag(value); + coder.stream().flush(); + assertEqualBytes(outputType, data, coder.toByteArray()); + + // Also try computing size. + assertEquals(data.length, CodedOutputStream.computeUInt64SizeNoTag(value)); + } + } + + // Try different block sizes. + for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { + // Only test 32-bit write if the value fits into an int. + if (value == (int) value) { + Coder coder = OutputType.STREAM.newCoder(blockSize); + coder.stream().writeUInt64NoTag((int) value); + coder.stream().flush(); + assertEqualBytes(OutputType.STREAM, data, coder.toByteArray()); + + ByteArrayOutputStream rawOutput = new ByteArrayOutputStream(); + CodedOutputStream output = CodedOutputStream.newInstance(rawOutput, blockSize); + output.writeUInt32NoTag((int) value); + output.flush(); + assertEqualBytes(OutputType.STREAM, data, rawOutput.toByteArray()); + } + + { + Coder coder = OutputType.STREAM.newCoder(blockSize); + coder.stream().writeUInt64NoTag(value); + coder.stream().flush(); + assertEqualBytes(OutputType.STREAM, data, coder.toByteArray()); + } + } + } + + private static void assertVarintRoundTrip(OutputType outputType, long value) throws Exception { + { + Coder coder = outputType.newCoder(10); + coder.stream().writeUInt64NoTag(value); + coder.stream().flush(); + byte[] bytes = coder.toByteArray(); + assertEquals( + outputType.name(), bytes.length, CodedOutputStream.computeUInt64SizeNoTag(value)); + CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(bytes)); + assertEquals(outputType.name(), value, input.readRawVarint64()); + } + + if (value == (int) value) { + Coder coder = outputType.newCoder(10); + coder.stream().writeUInt32NoTag((int) value); + coder.stream().flush(); + byte[] bytes = coder.toByteArray(); + assertEquals( + outputType.name(), bytes.length, CodedOutputStream.computeUInt32SizeNoTag((int) value)); + CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(bytes)); + assertEquals(outputType.name(), value, input.readRawVarint32()); + } + } } 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 d3deaa07..85b418c4 100644 --- a/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java @@ -73,20 +73,6 @@ public class DoubleArrayListTest extends TestCase { assertImmutable(list); } - public void testCopyConstructor() { - DoubleArrayList copy = new DoubleArrayList(TERTIARY_LIST); - assertEquals(TERTIARY_LIST, copy); - - copy = new DoubleArrayList(DoubleArrayList.emptyList()); - assertEquals(DoubleArrayList.emptyList(), copy); - - copy = new DoubleArrayList(asList(1D, 2D, 3D)); - assertEquals(asList(1D, 2D, 3D), copy); - - copy = new DoubleArrayList(Collections.<Double>emptyList()); - assertEquals(DoubleArrayList.emptyList(), copy); - } - public void testModificationWithIteration() { list.addAll(asList(1D, 2D, 3D, 4D)); Iterator<Double> iterator = list.iterator(); 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 a5e65424..88a75743 100644 --- a/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java @@ -73,20 +73,6 @@ public class FloatArrayListTest extends TestCase { assertImmutable(list); } - public void testCopyConstructor() { - FloatArrayList copy = new FloatArrayList(TERTIARY_LIST); - assertEquals(TERTIARY_LIST, copy); - - copy = new FloatArrayList(FloatArrayList.emptyList()); - assertEquals(FloatArrayList.emptyList(), copy); - - copy = new FloatArrayList(asList(1F, 2F, 3F)); - assertEquals(asList(1F, 2F, 3F), copy); - - copy = new FloatArrayList(Collections.<Float>emptyList()); - assertEquals(FloatArrayList.emptyList(), copy); - } - public void testModificationWithIteration() { list.addAll(asList(1F, 2F, 3F, 4F)); Iterator<Float> iterator = list.iterator(); 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 a92ba374..b7eaebf5 100644 --- a/java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java +++ b/java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java @@ -41,7 +41,7 @@ package com.google.protobuf; */ public class ForceFieldBuildersPreRun implements Runnable { - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public void run() { GeneratedMessage.enableAlwaysUseFieldBuildersForTesting(); } 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 8cd1f38d..a9b8b638 100644 --- a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java +++ b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java @@ -723,7 +723,7 @@ public class GeneratedMessageTest extends TestCase { public void testLiteExtensionMessageOrBuilder() throws Exception { TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder(); - TestUtil.setAllExtensions(builder); + TestUtilLite.setAllExtensions(builder); TestUtil.assertAllExtensionsSet(builder); TestAllExtensionsLite message = builder.build(); @@ -732,8 +732,8 @@ public class GeneratedMessageTest extends TestCase { public void testLiteExtensionRepeatedSetters() throws Exception { TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder(); - TestUtil.setAllExtensions(builder); - TestUtil.modifyRepeatedExtensions(builder); + TestUtilLite.setAllExtensions(builder); + TestUtilLite.modifyRepeatedExtensions(builder); TestUtil.assertRepeatedExtensionsModified(builder); TestAllExtensionsLite message = builder.build(); @@ -760,7 +760,7 @@ public class GeneratedMessageTest extends TestCase { } public void testLiteExtensionCopy() throws Exception { - TestAllExtensionsLite original = TestUtil.getAllLiteExtensionsSet(); + TestAllExtensionsLite original = TestUtilLite.getAllLiteExtensionsSet(); TestAllExtensionsLite copy = TestAllExtensionsLite.newBuilder(original).build(); TestUtil.assertAllExtensionsSet(copy); 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 3733eb30..efb8f3e2 100644 --- a/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java @@ -72,20 +72,6 @@ public class IntArrayListTest extends TestCase { list.makeImmutable(); assertImmutable(list); } - - public void testCopyConstructor() { - IntArrayList copy = new IntArrayList(TERTIARY_LIST); - assertEquals(TERTIARY_LIST, copy); - - copy = new IntArrayList(IntArrayList.emptyList()); - assertEquals(IntArrayList.emptyList(), copy); - - copy = new IntArrayList(asList(1, 2, 3)); - assertEquals(asList(1, 2, 3), copy); - - copy = new IntArrayList(Collections.<Integer>emptyList()); - assertEquals(IntArrayList.emptyList(), copy); - } public void testModificationWithIteration() { list.addAll(asList(1, 2, 3, 4)); diff --git a/java/core/src/test/java/com/google/protobuf/LiteTest.java b/java/core/src/test/java/com/google/protobuf/LiteTest.java index 9e503cc3..88c3e0b2 100644 --- a/java/core/src/test/java/com/google/protobuf/LiteTest.java +++ b/java/core/src/test/java/com/google/protobuf/LiteTest.java @@ -33,17 +33,25 @@ package com.google.protobuf; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; +import com.google.protobuf.UnittestImportLite.ImportEnumLite; +import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite; import com.google.protobuf.UnittestLite; 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.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 junit.framework.TestCase; @@ -59,6 +67,7 @@ import java.io.ObjectOutputStream; * @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 @@ -302,11 +311,9 @@ public class LiteTest extends TestCase { assertEquals( ForeignMessageLite.getDefaultInstance(), message.getOptionalForeignMessage()); - // LITE_RUNTIME doesn't implement equals so we compare on a property and - // ensure the property isn't set on foreignMessage. - assertEquals(3, builder.getOptionalForeignMessage().getC()); + assertEquals(foreignMessageBuilder.build(), builder.getOptionalForeignMessage()); messageAfterBuild = builder.build(); - assertEquals(3, messageAfterBuild.getOptionalForeignMessage().getC()); + assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getOptionalForeignMessage()); assertEquals( ForeignMessageLite.getDefaultInstance(), message.getOptionalForeignMessage()); @@ -314,7 +321,7 @@ public class LiteTest extends TestCase { assertEquals( ForeignMessageLite.getDefaultInstance(), builder.getOptionalForeignMessage()); - assertEquals(3, messageAfterBuild.getOptionalForeignMessage().getC()); + assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getOptionalForeignMessage()); message = builder.build(); OptionalGroup optionalGroup = OptionalGroup.newBuilder() @@ -339,17 +346,15 @@ public class LiteTest extends TestCase { builder.setOptionalGroup(optionalGroupBuilder); assertEquals( OptionalGroup.getDefaultInstance(), message.getOptionalGroup()); - // LITE_RUNTIME doesn't implement equals so we compare on a property and - // ensure the property isn't set on optionalGroup. - assertEquals(3, builder.getOptionalGroup().getA()); + assertEquals(optionalGroupBuilder.build(), builder.getOptionalGroup()); messageAfterBuild = builder.build(); - assertEquals(3, messageAfterBuild.getOptionalGroup().getA()); + assertEquals(optionalGroupBuilder.build(), messageAfterBuild.getOptionalGroup()); assertEquals( OptionalGroup.getDefaultInstance(), message.getOptionalGroup()); builder.clearOptionalGroup(); assertEquals( OptionalGroup.getDefaultInstance(), builder.getOptionalGroup()); - assertEquals(3, messageAfterBuild.getOptionalGroup().getA()); + assertEquals(optionalGroupBuilder.build(), messageAfterBuild.getOptionalGroup()); message = builder.build(); builder.setOptionalInt32(1); @@ -400,17 +405,16 @@ public class LiteTest extends TestCase { assertEquals( NestedMessage.getDefaultInstance(), message.getOptionalLazyMessage()); - // LITE_RUNTIME doesn't implement equals so we compare on a property. - assertEquals(3, builder.getOptionalLazyMessage().getBb()); + assertEquals(nestedMessageBuilder.build(), builder.getOptionalLazyMessage()); messageAfterBuild = builder.build(); - assertEquals(3, messageAfterBuild.getOptionalLazyMessage().getBb()); + assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getOptionalLazyMessage()); assertEquals( NestedMessage.getDefaultInstance(), message.getOptionalLazyMessage()); builder.clearOptionalLazyMessage(); assertEquals( NestedMessage.getDefaultInstance(), builder.getOptionalLazyMessage()); - assertEquals(3, messageAfterBuild.getOptionalLazyMessage().getBb()); + assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getOptionalLazyMessage()); message = builder.build(); builder.setOptionalSfixed32(1); @@ -1100,8 +1104,7 @@ public class LiteTest extends TestCase { assertEquals(0, message.getRepeatedForeignMessageCount()); builder.setRepeatedForeignMessage( 0, ForeignMessageLite.getDefaultInstance()); - // LITE_RUNTIME doesn't implement equals so we compare on a property. - assertEquals(3, messageAfterBuild.getRepeatedForeignMessage(0).getC()); + assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getRepeatedForeignMessage(0)); assertEquals( ForeignMessageLite.getDefaultInstance(), builder.getRepeatedForeignMessage(0)); @@ -1114,8 +1117,7 @@ public class LiteTest extends TestCase { builder.setRepeatedForeignMessage(0, foreignMessageBuilder); assertEquals( foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0)); - // LITE_RUNTIME doesn't implement equals so we compare on a property. - assertEquals(3, builder.getRepeatedForeignMessage(0).getC()); + assertEquals(foreignMessageBuilder.build(), builder.getRepeatedForeignMessage(0)); builder.clearRepeatedForeignMessage(); message = builder.build(); @@ -1148,9 +1150,7 @@ public class LiteTest extends TestCase { messageAfterBuild = builder.build(); assertEquals(0, message.getRepeatedGroupCount()); builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance()); - // LITE_RUNTIME doesn't implement equals so we compare on a property and - // ensure the property isn't set on repeatedGroup. - assertEquals(3, messageAfterBuild.getRepeatedGroup(0).getA()); + assertEquals(repeatedGroupBuilder.build(), messageAfterBuild.getRepeatedGroup(0)); assertEquals( RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0)); builder.clearRepeatedGroup(); @@ -1160,9 +1160,7 @@ public class LiteTest extends TestCase { messageAfterBuild = builder.build(); assertEquals(0, message.getRepeatedGroupCount()); builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance()); - // LITE_RUNTIME doesn't implement equals so we compare on a property and - // ensure the property isn't set on repeatedGroup. - assertEquals(3, messageAfterBuild.getRepeatedGroup(0).getA()); + assertEquals(repeatedGroupBuilder.build(), messageAfterBuild.getRepeatedGroup(0)); assertEquals( RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0)); builder.clearRepeatedGroup(); @@ -1210,9 +1208,7 @@ public class LiteTest extends TestCase { messageAfterBuild = builder.build(); assertEquals(0, message.getRepeatedLazyMessageCount()); builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance()); - // LITE_RUNTIME doesn't implement equals so we compare on a property and - // ensure the property isn't set on repeatedGroup. - assertEquals(3, messageAfterBuild.getRepeatedLazyMessage(0).getBb()); + assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getRepeatedLazyMessage(0)); assertEquals( NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0)); builder.clearRepeatedLazyMessage(); @@ -1222,9 +1218,7 @@ public class LiteTest extends TestCase { messageAfterBuild = builder.build(); assertEquals(0, message.getRepeatedLazyMessageCount()); builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance()); - // LITE_RUNTIME doesn't implement equals so we compare on a property and - // ensure the property isn't set on repeatedGroup. - assertEquals(3, messageAfterBuild.getRepeatedLazyMessage(0).getBb()); + assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getRepeatedLazyMessage(0)); assertEquals( NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0)); builder.clearRepeatedLazyMessage(); @@ -1456,7 +1450,7 @@ public class LiteTest extends TestCase { .setOptionalFloat(2.72f) .setOptionalDouble(3.14) .build(); - assertToStringEquals("optional_float: 2.72\noptional_double: 3.14", proto); + assertToStringEquals("optional_double: 3.14\noptional_float: 2.72", proto); } public void testToStringStringFields() throws Exception { @@ -1511,7 +1505,7 @@ public class LiteTest extends TestCase { .setC(3)) .build(); assertToStringEquals( - "optional_foreign_message {\n c: 3\n}\noptional_foreign_enum: FOREIGN_LITE_BAR", + "optional_foreign_enum: FOREIGN_LITE_BAR\noptional_foreign_message {\n c: 3\n}", proto); } @@ -1546,6 +1540,27 @@ public class LiteTest extends TestCase { "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 @@ -1598,4 +1613,617 @@ public class LiteTest extends TestCase { 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 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 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); + } + + // 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)); + } + + 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(); + } } 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 1bd094f7..0a8f9ed2 100644 --- a/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java @@ -73,20 +73,6 @@ public class LongArrayListTest extends TestCase { assertImmutable(list); } - public void testCopyConstructor() { - LongArrayList copy = new LongArrayList(TERTIARY_LIST); - assertEquals(TERTIARY_LIST, copy); - - copy = new LongArrayList(LongArrayList.emptyList()); - assertEquals(LongArrayList.emptyList(), copy); - - copy = new LongArrayList(asList(1L, 2L, 3L)); - assertEquals(asList(1L, 2L, 3L), copy); - - copy = new LongArrayList(Collections.<Long>emptyList()); - assertEquals(LongArrayList.emptyList(), copy); - } - public void testModificationWithIteration() { list.addAll(asList(1L, 2L, 3L, 4L)); Iterator<Long> iterator = list.iterator(); 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 9d4b6b94..30842d2c 100644 --- a/java/core/src/test/java/com/google/protobuf/ParserTest.java +++ b/java/core/src/test/java/com/google/protobuf/ParserTest.java @@ -179,16 +179,16 @@ public class ParserTest extends TestCase { public void testParseExtensions() throws Exception { assertRoundTripEquals(TestUtil.getAllExtensionsSet(), TestUtil.getExtensionRegistry()); - assertRoundTripEquals(TestUtil.getAllLiteExtensionsSet(), - TestUtil.getExtensionRegistryLite()); + assertRoundTripEquals( + TestUtilLite.getAllLiteExtensionsSet(), TestUtilLite.getExtensionRegistryLite()); } public void testParsePacked() throws Exception { assertRoundTripEquals(TestUtil.getPackedSet()); assertRoundTripEquals(TestUtil.getPackedExtensionsSet(), TestUtil.getExtensionRegistry()); - assertRoundTripEquals(TestUtil.getLitePackedExtensionsSet(), - TestUtil.getExtensionRegistryLite()); + assertRoundTripEquals( + TestUtilLite.getLitePackedExtensionsSet(), TestUtilLite.getExtensionRegistryLite()); } public void testParseDelimitedTo() throws Exception { @@ -198,8 +198,7 @@ public class ParserTest extends TestCase { normalMessage.writeDelimitedTo(output); // Write MessageLite with packed extension fields. - TestPackedExtensionsLite packedMessage = - TestUtil.getLitePackedExtensionsSet(); + TestPackedExtensionsLite packedMessage = TestUtilLite.getLitePackedExtensionsSet(); packedMessage.writeDelimitedTo(output); InputStream input = new ByteArrayInputStream(output.toByteArray()); @@ -208,8 +207,9 @@ public class ParserTest extends TestCase { normalMessage.getParserForType().parseDelimitedFrom(input)); assertMessageEquals( packedMessage, - packedMessage.getParserForType().parseDelimitedFrom( - input, TestUtil.getExtensionRegistryLite())); + packedMessage + .getParserForType() + .parseDelimitedFrom(input, TestUtilLite.getExtensionRegistryLite())); } public void testParseUnknownFields() throws Exception { 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 245c3dee..3f45e226 100644 --- a/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java @@ -63,20 +63,6 @@ public class ProtobufArrayListTest extends TestCase { assertImmutable(ProtobufArrayList.<Integer>emptyList()); } - public void testCopyConstructor() { - ProtobufArrayList<Integer> copy = new ProtobufArrayList<Integer>(TERTIARY_LIST); - assertEquals(TERTIARY_LIST, copy); - - copy = new ProtobufArrayList<Integer>(IntArrayList.emptyList()); - assertEquals(ProtobufArrayList.emptyList(), copy); - - copy = new ProtobufArrayList<Integer>(asList(1, 2, 3)); - assertEquals(asList(1, 2, 3), copy); - - copy = new ProtobufArrayList<Integer>(Collections.<Integer>emptyList()); - assertEquals(ProtobufArrayList.emptyList(), copy); - } - public void testModificationWithIteration() { list.addAll(asList(1, 2, 3, 4)); Iterator<Integer> iterator = list.iterator(); 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 7f3439d0..b902737d 100644 --- a/java/core/src/test/java/com/google/protobuf/ServiceTest.java +++ b/java/core/src/test/java/com/google/protobuf/ServiceTest.java @@ -175,12 +175,14 @@ public class ServiceTest extends TestCase { MethodDescriptor fooMethod = ServiceWithNoOuter.getDescriptor().findMethodByName("Foo"); MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance(); - RpcCallback<Message> callback = new RpcCallback<Message>() { - public void run(Message parameter) { - // No reason this should be run. - fail(); - } - }; + RpcCallback<Message> callback = + new RpcCallback<Message>() { + @Override + public void run(Message parameter) { + // No reason this should be run. + fail(); + } + }; RpcCallback<TestAllTypes> specializedCallback = RpcUtil.specializeCallback(callback); @@ -290,7 +292,9 @@ public class ServiceTest extends TestCase { public boolean isCalled() { return called; } public void reset() { called = false; } - public void run(Type message) { called = true; } + @Override + public void run(Type message) { + called = true; } } /** Implementation of the wrapsCallback() argument matcher. */ @@ -301,6 +305,7 @@ public class ServiceTest extends TestCase { this.callback = callback; } + @Override @SuppressWarnings("unchecked") public boolean matches(Object actual) { if (!(actual instanceof RpcCallback)) { @@ -313,6 +318,7 @@ public class ServiceTest extends TestCase { return callback.isCalled(); } + @Override public void appendTo(StringBuffer buffer) { buffer.append("wrapsCallback(mockCallback)"); } 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 366086d3..e96ecd65 100644 --- a/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java +++ b/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java @@ -56,14 +56,17 @@ public class SmallSortedMapTest extends TestCase { this.value = value; } + @Override public K getKey() { return key; } + @Override public V getValue() { return value; } + @Override public V setValue(V value) { V oldValue = this.value; this.value = value; 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 53d65428..08b2a76d 100644 --- a/java/core/src/test/java/com/google/protobuf/TestUtil.java +++ b/java/core/src/test/java/com/google/protobuf/TestUtil.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; @@ -216,12 +214,7 @@ import static protobuf_unittest.UnittestProto.repeatedUint32Extension; import static protobuf_unittest.UnittestProto.repeatedUint64Extension; import com.google.protobuf.UnittestImportLite.ImportEnumLite; -import com.google.protobuf.UnittestImportLite.ImportMessageLite; -import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite; -import com.google.protobuf.UnittestLite; import com.google.protobuf.UnittestLite.ForeignEnumLite; -import com.google.protobuf.UnittestLite.ForeignMessageLite; -import com.google.protobuf.UnittestLite.TestAllExtensionsLite; import com.google.protobuf.UnittestLite.TestAllExtensionsLiteOrBuilder; import com.google.protobuf.UnittestLite.TestAllTypesLite; import com.google.protobuf.UnittestLite.TestPackedExtensionsLite; @@ -287,16 +280,6 @@ public final class TestUtil { } /** - * 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(); - setAllFields(builder); - return builder; - } - - /** * Get a {@code TestAllExtensions} with all fields set as they would be by * {@link #setAllExtensions(TestAllExtensions.Builder)}. */ @@ -306,12 +289,6 @@ public final class TestUtil { return builder.build(); } - public static TestAllExtensionsLite getAllLiteExtensionsSet() { - TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder(); - setAllExtensions(builder); - return builder.build(); - } - public static TestPackedTypes getPackedSet() { TestPackedTypes.Builder builder = TestPackedTypes.newBuilder(); setPackedFields(builder); @@ -330,157 +307,6 @@ public final class TestUtil { return builder.build(); } - public static TestPackedExtensionsLite getLitePackedExtensionsSet() { - TestPackedExtensionsLite.Builder builder = - TestPackedExtensionsLite.newBuilder(); - setPackedExtensions(builder); - return builder.build(); - } - - /** - * 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.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.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.setOptionalNestedEnum (TestAllTypesLite.NestedEnum.BAZ); - builder.setOptionalForeignEnum(ForeignEnumLite.FOREIGN_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.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.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.addRepeatedNestedEnum (TestAllTypesLite.NestedEnum.BAR); - builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_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.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.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.addRepeatedNestedEnum (TestAllTypesLite.NestedEnum.BAZ); - builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_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.setDefaultSfixed32(409); - builder.setDefaultSfixed64(410); - builder.setDefaultFloat (411); - builder.setDefaultDouble (412); - builder.setDefaultBool (false); - builder.setDefaultString ("415"); - builder.setDefaultBytes (toBytes("416")); - - builder.setDefaultNestedEnum (TestAllTypesLite.NestedEnum.FOO); - builder.setDefaultForeignEnum(ForeignEnumLite.FOREIGN_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.setOneofString("603"); - builder.setOneofBytes(toBytes("604")); - } - /** * Set every field of {@code message} to the values expected by * {@code assertAllFieldsSet()}. @@ -1370,23 +1196,13 @@ public final class TestUtil { return registry.getUnmodifiable(); } - public static ExtensionRegistryLite getExtensionRegistryLite() { - ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); - registerAllExtensionsLite(registry); - return registry.getUnmodifiable(); - } - /** * Register all of {@code TestAllExtensions}'s extensions with the * given {@link ExtensionRegistry}. */ public static void registerAllExtensions(ExtensionRegistry registry) { UnittestProto.registerAllExtensions(registry); - registerAllExtensionsLite(registry); - } - - public static void registerAllExtensionsLite(ExtensionRegistryLite registry) { - UnittestLite.registerAllExtensions(registry); + TestUtilLite.registerAllExtensionsLite(registry); } /** @@ -2180,195 +1996,6 @@ public final class TestUtil { // Lite extensions /** - * 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(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(optionalNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ); - message.setExtension(optionalForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ); - message.setExtension(optionalImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ); - - message.setExtension(optionalStringPieceExtensionLite, "124"); - message.setExtension(optionalCordExtensionLite, "125"); - - // ----------------------------------------------------------------- - - 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(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAR); - message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR); - message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAR); - - message.addExtension(repeatedStringPieceExtensionLite, "224"); - 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(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(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ); - message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ); - message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ); - - message.addExtension(repeatedStringPieceExtensionLite, "324"); - message.addExtension(repeatedCordExtensionLite, "325"); - - // ----------------------------------------------------------------- - - 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(defaultNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.FOO); - message.setExtension(defaultForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_FOO); - message.setExtension(defaultImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_FOO); - - message.setExtension(defaultStringPieceExtensionLite, "424"); - message.setExtension(defaultCordExtensionLite, "425"); - - message.setExtension(oneofUint32ExtensionLite, 601); - message.setExtension(oneofNestedMessageExtensionLite, - TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build()); - message.setExtension(oneofStringExtensionLite, "603"); - message.setExtension(oneofBytesExtensionLite, toBytes("604")); - } - - // ------------------------------------------------------------------- - - /** - * 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); - 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(repeatedForeignEnumExtensionLite, 1, ForeignEnumLite.FOREIGN_LITE_FOO); - message.setExtension(repeatedImportEnumExtensionLite , 1, ImportEnumLite.IMPORT_LITE_FOO); - - message.setExtension(repeatedStringPieceExtensionLite, 1, "524"); - message.setExtension(repeatedCordExtensionLite, 1, "525"); - } - - // ------------------------------------------------------------------- - - /** * Assert (using {@code junit.framework.Assert}} that all extensions of * {@code message} are set to the values assigned by {@code setAllExtensions}. */ @@ -2867,38 +2494,6 @@ public final class TestUtil { assertEqualsExactType("525", message.getExtension(repeatedCordExtensionLite, 1)); } - 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(packedSfixed32ExtensionLite, 609); - message.addExtension(packedSfixed64ExtensionLite, 610L); - 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(packedSfixed32ExtensionLite, 709); - message.addExtension(packedSfixed64ExtensionLite, 710L); - message.addExtension(packedFloatExtensionLite , 711F); - message.addExtension(packedDoubleExtensionLite , 712D); - message.addExtension(packedBoolExtensionLite , false); - message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ); - } - public static void assertPackedExtensionsSet(TestPackedExtensionsLite message) { Assert.assertEquals(2, message.getExtensionCount(packedInt32ExtensionLite )); Assert.assertEquals(2, message.getExtensionCount(packedInt64ExtensionLite )); @@ -4250,7 +3845,7 @@ public final class TestUtil { private int invalidations; - //@Override (Java 1.6 override semantics, but we must support 1.5) + @Override public void markDirty() { invalidations++; } diff --git a/java/core/src/test/java/com/google/protobuf/TestUtilLite.java b/java/core/src/test/java/com/google/protobuf/TestUtilLite.java new file mode 100644 index 00000000..8f33fa14 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/TestUtilLite.java @@ -0,0 +1,559 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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.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; +import static com.google.protobuf.UnittestLite.defaultDoubleExtensionLite; +import static com.google.protobuf.UnittestLite.defaultFixed32ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultFixed64ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultFloatExtensionLite; +import static com.google.protobuf.UnittestLite.defaultForeignEnumExtensionLite; +import static com.google.protobuf.UnittestLite.defaultImportEnumExtensionLite; +import static com.google.protobuf.UnittestLite.defaultInt32ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultInt64ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultNestedEnumExtensionLite; +import static com.google.protobuf.UnittestLite.defaultSfixed32ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultSfixed64ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultSint32ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultSint64ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultStringExtensionLite; +import static com.google.protobuf.UnittestLite.defaultStringPieceExtensionLite; +import static com.google.protobuf.UnittestLite.defaultUint32ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultUint64ExtensionLite; +import static com.google.protobuf.UnittestLite.oneofBytesExtensionLite; +import static com.google.protobuf.UnittestLite.oneofNestedMessageExtensionLite; +import static com.google.protobuf.UnittestLite.oneofStringExtensionLite; +import static com.google.protobuf.UnittestLite.oneofUint32ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalBoolExtensionLite; +import static com.google.protobuf.UnittestLite.optionalBytesExtensionLite; +import static com.google.protobuf.UnittestLite.optionalCordExtensionLite; +import static com.google.protobuf.UnittestLite.optionalDoubleExtensionLite; +import static com.google.protobuf.UnittestLite.optionalFixed32ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalFixed64ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalFloatExtensionLite; +import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite; +import static com.google.protobuf.UnittestLite.optionalForeignMessageExtensionLite; +import static com.google.protobuf.UnittestLite.optionalGroupExtensionLite; +import static com.google.protobuf.UnittestLite.optionalImportEnumExtensionLite; +import static com.google.protobuf.UnittestLite.optionalImportMessageExtensionLite; +import static com.google.protobuf.UnittestLite.optionalInt32ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalInt64ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalLazyMessageExtensionLite; +import static com.google.protobuf.UnittestLite.optionalNestedEnumExtensionLite; +import static com.google.protobuf.UnittestLite.optionalNestedMessageExtensionLite; +import static com.google.protobuf.UnittestLite.optionalPublicImportMessageExtensionLite; +import static com.google.protobuf.UnittestLite.optionalSfixed32ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalSfixed64ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalSint32ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalSint64ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalStringExtensionLite; +import static com.google.protobuf.UnittestLite.optionalStringPieceExtensionLite; +import static com.google.protobuf.UnittestLite.optionalUint32ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalUint64ExtensionLite; +import static com.google.protobuf.UnittestLite.packedBoolExtensionLite; +import static com.google.protobuf.UnittestLite.packedDoubleExtensionLite; +import static com.google.protobuf.UnittestLite.packedEnumExtensionLite; +import static com.google.protobuf.UnittestLite.packedFixed32ExtensionLite; +import static com.google.protobuf.UnittestLite.packedFixed64ExtensionLite; +import static com.google.protobuf.UnittestLite.packedFloatExtensionLite; +import static com.google.protobuf.UnittestLite.packedInt32ExtensionLite; +import static com.google.protobuf.UnittestLite.packedInt64ExtensionLite; +import static com.google.protobuf.UnittestLite.packedSfixed32ExtensionLite; +import static com.google.protobuf.UnittestLite.packedSfixed64ExtensionLite; +import static com.google.protobuf.UnittestLite.packedSint32ExtensionLite; +import static com.google.protobuf.UnittestLite.packedSint64ExtensionLite; +import static com.google.protobuf.UnittestLite.packedUint32ExtensionLite; +import static com.google.protobuf.UnittestLite.packedUint64ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedBoolExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedBytesExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedCordExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedDoubleExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedFixed32ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedFixed64ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedFloatExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedForeignEnumExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedForeignMessageExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedGroupExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedImportEnumExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedImportMessageExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedInt32ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedInt64ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedLazyMessageExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedNestedEnumExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedNestedMessageExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedSfixed32ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedSfixed64ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedSint32ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedSint64ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedStringExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedStringPieceExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedUint32ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedUint64ExtensionLite; + +import com.google.protobuf.UnittestImportLite.ImportEnumLite; +import com.google.protobuf.UnittestImportLite.ImportMessageLite; +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.TestPackedExtensionsLite; + +/** + * Contains methods for setting fields of {@code TestAllTypesLite}, {@code TestAllExtensionsLite}, + * and {@code TestPackedExtensionsLite}. This is analogous to the functionality in TestUtil.java but + * does not depend on the presence of any non-lite protos. + * + * <p>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)); + } + + /** + * 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(); + setAllFields(builder); + return 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(); + setAllExtensions(builder); + return builder.build(); + } + + public static TestPackedExtensionsLite getLitePackedExtensionsSet() { + TestPackedExtensionsLite.Builder builder = TestPackedExtensionsLite.newBuilder(); + setPackedExtensions(builder); + return builder.build(); + } + + /** + * 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.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.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.setOptionalNestedEnum (TestAllTypesLite.NestedEnum.BAZ); + builder.setOptionalForeignEnum(ForeignEnumLite.FOREIGN_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.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.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.addRepeatedNestedEnum (TestAllTypesLite.NestedEnum.BAR); + builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_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.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.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.addRepeatedNestedEnum (TestAllTypesLite.NestedEnum.BAZ); + builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_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.setDefaultSfixed32(409); + builder.setDefaultSfixed64(410); + builder.setDefaultFloat (411); + builder.setDefaultDouble (412); + builder.setDefaultBool (false); + builder.setDefaultString ("415"); + builder.setDefaultBytes (toBytes("416")); + + builder.setDefaultNestedEnum (TestAllTypesLite.NestedEnum.FOO); + builder.setDefaultForeignEnum(ForeignEnumLite.FOREIGN_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.setOneofString("603"); + builder.setOneofBytes(toBytes("604")); + } + + /** + * Get an unmodifiable {@link ExtensionRegistryLite} containing all the + * extensions of {@code TestAllExtensionsLite}. + */ + public static ExtensionRegistryLite getExtensionRegistryLite() { + ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); + registerAllExtensionsLite(registry); + return registry.getUnmodifiable(); + } + + /** + * Register all of {@code TestAllExtensionsLite}'s extensions with the + * given {@link ExtensionRegistryLite}. + */ + public static void registerAllExtensionsLite(ExtensionRegistryLite registry) { + UnittestLite.registerAllExtensions(registry); + } + + // =================================================================== + // Lite extensions + + /** + * 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(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(optionalNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ); + message.setExtension(optionalForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ); + message.setExtension(optionalImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ); + + message.setExtension(optionalStringPieceExtensionLite, "124"); + message.setExtension(optionalCordExtensionLite, "125"); + + // ----------------------------------------------------------------- + + 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(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAR); + message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR); + message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAR); + + message.addExtension(repeatedStringPieceExtensionLite, "224"); + 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(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(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ); + message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ); + message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ); + + message.addExtension(repeatedStringPieceExtensionLite, "324"); + message.addExtension(repeatedCordExtensionLite, "325"); + + // ----------------------------------------------------------------- + + 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(defaultNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.FOO); + message.setExtension(defaultForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_FOO); + message.setExtension(defaultImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_FOO); + + message.setExtension(defaultStringPieceExtensionLite, "424"); + message.setExtension(defaultCordExtensionLite, "425"); + + message.setExtension(oneofUint32ExtensionLite, 601); + message.setExtension(oneofNestedMessageExtensionLite, + TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build()); + message.setExtension(oneofStringExtensionLite, "603"); + message.setExtension(oneofBytesExtensionLite, toBytes("604")); + } + + // ------------------------------------------------------------------- + + /** + * 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); + 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(repeatedForeignEnumExtensionLite, 1, ForeignEnumLite.FOREIGN_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(packedSfixed32ExtensionLite, 609); + message.addExtension(packedSfixed64ExtensionLite, 610L); + 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(packedSfixed32ExtensionLite, 709); + message.addExtension(packedSfixed64ExtensionLite, 710L); + 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/TextFormatTest.java b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java index 3f47d924..63c17cd0 100644 --- a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java +++ b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java @@ -775,11 +775,14 @@ public class TextFormatTest extends TestCase { public void testParseBoolean() throws Exception { String goodText = "repeated_bool: t repeated_bool : 0\n" + - "repeated_bool :f repeated_bool:1"; + "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"; TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TextFormat.merge(goodText, builder); 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 8c9dcafe..32380f70 100644 --- a/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java +++ b/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java @@ -50,6 +50,7 @@ import java.util.Map; * @author kenton@google.com (Kenton Varda) */ public class UnknownFieldSetTest extends TestCase { + @Override public void setUp() throws Exception { descriptor = TestAllTypes.getDescriptor(); allFields = TestUtil.getAllSet(); 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 b3aabb8f..e66b371c 100644 --- a/java/core/src/test/java/com/google/protobuf/WireFormatTest.java +++ b/java/core/src/test/java/com/google/protobuf/WireFormatTest.java @@ -132,7 +132,7 @@ public class WireFormatTest extends TestCase { // so if we serialize a TestAllExtensions then parse it as TestAllTypes // it should work. - TestAllExtensionsLite message = TestUtil.getAllLiteExtensionsSet(); + TestAllExtensionsLite message = TestUtilLite.getAllLiteExtensionsSet(); ByteString rawBytes = message.toByteString(); assertEquals(rawBytes.size(), message.getSerializedSize()); @@ -144,7 +144,7 @@ public class WireFormatTest extends TestCase { public void testSerializePackedExtensionsLite() throws Exception { // TestPackedTypes and TestPackedExtensions should have compatible wire // formats; check that they serialize to the same string. - TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet(); + TestPackedExtensionsLite message = TestUtilLite.getLitePackedExtensionsSet(); ByteString rawBytes = message.toByteString(); TestPackedTypes message2 = TestUtil.getPackedSet(); @@ -190,7 +190,7 @@ public class WireFormatTest extends TestCase { TestAllTypes message = TestUtil.getAllSet(); ByteString rawBytes = message.toByteString(); - ExtensionRegistryLite registry_lite = TestUtil.getExtensionRegistryLite(); + ExtensionRegistryLite registry_lite = TestUtilLite.getExtensionRegistryLite(); TestAllExtensionsLite message2 = TestAllExtensionsLite.parseFrom(rawBytes, registry_lite); @@ -208,10 +208,10 @@ public class WireFormatTest extends TestCase { public void testParsePackedExtensionsLite() throws Exception { // Ensure that packed extensions can be properly parsed. - TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet(); + TestPackedExtensionsLite message = TestUtilLite.getLitePackedExtensionsSet(); ByteString rawBytes = message.toByteString(); - ExtensionRegistryLite registry = TestUtil.getExtensionRegistryLite(); + ExtensionRegistryLite registry = TestUtilLite.getExtensionRegistryLite(); TestPackedExtensionsLite message2 = TestPackedExtensionsLite.parseFrom(rawBytes, registry); 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 f75484de..6eef42c5 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,9 +34,6 @@ syntax = "proto2"; package protobuf_unittest.lite_equals_and_hash; -// This proto definition is used to test that java_generate_equals_and_hash -// works correctly with the LITE_RUNTIME. -option java_generate_equals_and_hash = true; option optimize_for = LITE_RUNTIME; message TestOneofEquals { diff --git a/java/lite/generate-sources-build.xml b/java/lite/generate-sources-build.xml new file mode 100644 index 00000000..89c21c13 --- /dev/null +++ b/java/lite/generate-sources-build.xml @@ -0,0 +1,20 @@ +<project name="generate-sources"> + <echo message="Running protoc ..."/> + <mkdir dir="${generated.sources.lite.dir}"/> + <exec executable="${protoc}"> + <arg value="--java_out=lite:${generated.sources.lite.dir}"/> + <arg value="--proto_path=${protobuf.source.dir}"/> + <arg value="${protobuf.source.dir}/google/protobuf/any.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/api.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/descriptor.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/duration.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/empty.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/field_mask.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/source_context.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/struct.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/timestamp.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/type.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/wrappers.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/compiler/plugin.proto"/> + </exec> +</project> diff --git a/java/lite/generate-test-sources-build.xml b/java/lite/generate-test-sources-build.xml new file mode 100644 index 00000000..cdd1ee89 --- /dev/null +++ b/java/lite/generate-test-sources-build.xml @@ -0,0 +1,43 @@ +<project name="generate-test-sources"> + <mkdir dir="${generated.testsources.lite.dir}"/> + <exec executable="${protoc}"> + <arg value="--java_out=lite:${generated.testsources.lite.dir}"/> + <arg value="--proto_path=${protobuf.source.dir}"/> + <arg value="--proto_path=${test.proto.dir}"/> + <arg value="${protobuf.source.dir}/google/protobuf/unittest.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/unittest_import.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/unittest_mset.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/unittest_mset_wire_format.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/unittest_optimize_for.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/unittest_custom_options.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/unittest_lite.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_lite.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public_lite.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/unittest_lite_imports_nonlite.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/unittest_enormous_descriptor.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/unittest_no_generic_services.proto"/> + <arg value="${protobuf.source.dir}/google/protobuf/unittest_well_known_types.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/lazy_fields_lite.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/lite_equals_and_hash.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/multiple_files_test.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/nested_builders_test.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/nested_extension.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/nested_extension_lite.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/non_nested_extension.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/non_nested_extension_lite.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test2.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test3.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/test_bad_identifiers.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/test_check_utf8.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/test_check_utf8_size.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/test_custom_options.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/any_test.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/field_presence_test.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/map_for_proto2_lite_test.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/map_for_proto2_test.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/map_test.proto"/> + <arg value="${test.proto.dir}/com/google/protobuf/map_initialization_order_test.proto"/> + </exec> +</project> diff --git a/java/lite/pom.xml b/java/lite/pom.xml index 70c7d047..23cb4f78 100644 --- a/java/lite/pom.xml +++ b/java/lite/pom.xml @@ -50,7 +50,7 @@ <phase>generate-sources</phase> <configuration> <target> - <ant antfile="${core.root}/generate-sources-build.xml"/> + <ant antfile="generate-sources-build.xml"/> </target> </configuration> <goals> @@ -64,7 +64,7 @@ <phase>generate-test-sources</phase> <configuration> <target> - <ant antfile="${core.root}/generate-test-sources-build.xml"/> + <ant antfile="generate-test-sources-build.xml"/> </target> </configuration> <goals> @@ -78,8 +78,8 @@ <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> - <generatedSourcesDirectory>${generated.sources.dir}</generatedSourcesDirectory> - <generatedTestSourcesDirectory>${generated.testsources.dir}</generatedTestSourcesDirectory> + <generatedSourcesDirectory>${generated.sources.lite.dir}</generatedSourcesDirectory> + <generatedTestSourcesDirectory>${generated.testsources.lite.dir}</generatedTestSourcesDirectory> <includes> <include>**/AbstractMessageLite.java</include> <include>**/AbstractParser.java</include> diff --git a/java/pom.xml b/java/pom.xml index 787bc534..e8dc5ded 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -33,6 +33,8 @@ <test.proto.dir>src/test/proto</test.proto.dir> <generated.sources.dir>${project.build.directory}/generated-sources</generated.sources.dir> <generated.testsources.dir>${project.build.directory}/generated-test-sources</generated.testsources.dir> + <generated.sources.lite.dir>${project.build.directory}/generated-sources-lite</generated.sources.lite.dir> + <generated.testsources.lite.dir>${project.build.directory}/generated-test-sources-lite</generated.testsources.lite.dir> </properties> <licenses> diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java new file mode 100644 index 00000000..03c0d579 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java @@ -0,0 +1,553 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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 com.google.protobuf.Descriptors.OneofDescriptor; +import com.google.protobuf.Internal.EnumLite; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +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. + * + * @author kenton@google.com Kenton Varda + */ +public abstract class AbstractMessage + // TODO(dweis): Update GeneratedMessage to parameterize with MessageType and BuilderType. + extends AbstractMessageLite + implements Message { + + @Override + public boolean isInitialized() { + return MessageReflection.isInitialized(this); + } + + + @Override + public List<String> findInitializationErrors() { + return MessageReflection.findMissingFields(this); + } + + @Override + public String getInitializationErrorString() { + return MessageReflection.delimitWithCommas(findInitializationErrors()); + } + + /** TODO(jieluo): Clear it when all subclasses have implemented this method. */ + @Override + public boolean hasOneof(OneofDescriptor oneof) { + throw new UnsupportedOperationException("hasOneof() is not implemented."); + } + + /** TODO(jieluo): Clear it when all subclasses have implemented this method. */ + @Override + public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) { + throw new UnsupportedOperationException( + "getOneofFieldDescriptor() is not implemented."); + } + + @Override + public final String toString() { + return TextFormat.printToString(this); + } + + @Override + public void writeTo(final CodedOutputStream output) throws IOException { + MessageReflection.writeMessageTo(this, getAllFields(), output, false); + } + + protected int memoizedSize = -1; + + @Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) { + return size; + } + + memoizedSize = MessageReflection.getSerializedSize(this, getAllFields()); + return memoizedSize; + } + + @Override + public boolean equals(final Object other) { + if (other == this) { + return true; + } + if (!(other instanceof Message)) { + return false; + } + final Message otherMessage = (Message) other; + if (getDescriptorForType() != otherMessage.getDescriptorForType()) { + return false; + } + return compareFields(getAllFields(), otherMessage.getAllFields()) && + getUnknownFields().equals(otherMessage.getUnknownFields()); + } + + @Override + public int hashCode() { + int hash = memoizedHashCode; + if (hash == 0) { + hash = 41; + hash = (19 * hash) + getDescriptorForType().hashCode(); + hash = hashFields(hash, getAllFields()); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + } + return hash; + } + + private static ByteString toByteString(Object value) { + if (value instanceof byte[]) { + return ByteString.copyFrom((byte[]) value); + } else { + return (ByteString) value; + } + } + + /** + * 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 toByteString(a).equals(toByteString(b)); + } + + /** + * 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(); + Iterator iterator = list.iterator(); + Message entry = (Message) iterator.next(); + Descriptors.Descriptor descriptor = entry.getDescriptorForType(); + Descriptors.FieldDescriptor key = descriptor.findFieldByName("key"); + Descriptors.FieldDescriptor value = descriptor.findFieldByName("value"); + Object fieldValue = entry.getField(value); + if (fieldValue instanceof EnumValueDescriptor) { + fieldValue = ((EnumValueDescriptor) fieldValue).getNumber(); + } + result.put(entry.getField(key), fieldValue); + while (iterator.hasNext()) { + entry = (Message) iterator.next(); + fieldValue = entry.getField(value); + if (fieldValue instanceof EnumValueDescriptor) { + fieldValue = ((EnumValueDescriptor) fieldValue).getNumber(); + } + result.put(entry.getField(key), fieldValue); + } + return result; + } + + /** + * 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); + Map mb = convertMapEntryListToMap((List) b); + return MapFieldLite.equals(ma, mb); + } + + /** + * 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 reprensent 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<FieldDescriptor, Object> a, + Map<FieldDescriptor, Object> b) { + if (a.size() != b.size()) { + return false; + } + for (FieldDescriptor descriptor : a.keySet()) { + if (!b.containsKey(descriptor)) { + return false; + } + Object value1 = a.get(descriptor); + Object value2 = b.get(descriptor); + if (descriptor.getType() == FieldDescriptor.Type.BYTES) { + if (descriptor.isRepeated()) { + List list1 = (List) value1; + List list2 = (List) value2; + if (list1.size() != list2.size()) { + return false; + } + for (int i = 0; i < list1.size(); i++) { + if (!compareBytes(list1.get(i), list2.get(i))) { + return false; + } + } + } else { + // Compares a singular bytes field. + if (!compareBytes(value1, value2)) { + return false; + } + } + } else if (descriptor.isMapField()) { + if (!compareMapField(value1, value2)) { + return false; + } + } else { + // Compare non-bytes fields. + if (!value1.equals(value2)) { + return false; + } + } + } + return true; + } + + /** + * 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)); + } + + /** Get a hash code for given fields and values, using the given seed. */ + @SuppressWarnings("unchecked") + protected static int hashFields(int hash, Map<FieldDescriptor, Object> map) { + for (Map.Entry<FieldDescriptor, Object> entry : map.entrySet()) { + FieldDescriptor field = entry.getKey(); + Object value = entry.getValue(); + hash = (37 * hash) + field.getNumber(); + if (field.isMapField()) { + hash = (53 * hash) + hashMapField(value); + } else if (field.getType() != FieldDescriptor.Type.ENUM){ + hash = (53 * hash) + value.hashCode(); + } else if (field.isRepeated()) { + List<? extends EnumLite> list = (List<? extends EnumLite>) value; + hash = (53 * hash) + Internal.hashEnumList(list); + } else { + hash = (53 * hash) + Internal.hashEnum((EnumLite) value); + } + } + return hash; + } + + /** + * Package private helper method for AbstractParser to create + * UninitializedMessageException with missing field information. + */ + @Override + UninitializedMessageException newUninitializedMessageException() { + return Builder.newUninitializedMessageException(this); + } + + // ================================================================= + + /** + * 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<BuilderType extends Builder<BuilderType>> + extends AbstractMessageLite.Builder + implements Message.Builder { + // The compiler produces an error if this is not declared explicitly. + @Override + public abstract BuilderType clone(); + + /** TODO(jieluo): Clear it when all subclasses have implemented this method. */ + @Override + public boolean hasOneof(OneofDescriptor oneof) { + throw new UnsupportedOperationException("hasOneof() is not implemented."); + } + + /** TODO(jieluo): Clear it when all subclasses have implemented this method. */ + @Override + public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) { + throw new UnsupportedOperationException( + "getOneofFieldDescriptor() is not implemented."); + } + + /** TODO(jieluo): Clear it when all subclasses have implemented this method. */ + @Override + public BuilderType clearOneof(OneofDescriptor oneof) { + throw new UnsupportedOperationException("clearOneof() is not implemented."); + } + + @Override + public BuilderType clear() { + for (final Map.Entry<FieldDescriptor, Object> entry : + getAllFields().entrySet()) { + clearField(entry.getKey()); + } + return (BuilderType) this; + } + + @Override + public List<String> findInitializationErrors() { + return MessageReflection.findMissingFields(this); + } + + @Override + public String getInitializationErrorString() { + return MessageReflection.delimitWithCommas(findInitializationErrors()); + } + + @Override + protected BuilderType internalMergeFrom(AbstractMessageLite other) { + return mergeFrom((Message) other); + } + + @Override + public BuilderType mergeFrom(final Message other) { + if (other.getDescriptorForType() != getDescriptorForType()) { + throw new IllegalArgumentException( + "mergeFrom(Message) can only merge messages of the same type."); + } + + // Note: We don't attempt to verify that other's fields have valid + // types. Doing so would be a losing battle. We'd have to verify + // all sub-messages as well, and we'd have to make copies of all of + // them to insure that they don't change after verification (since + // the Message interface itself cannot enforce immutability of + // implementations). + // TODO(kenton): Provide a function somewhere called makeDeepCopy() + // which allows people to make secure deep copies of messages. + + for (final Map.Entry<FieldDescriptor, Object> entry : + other.getAllFields().entrySet()) { + final FieldDescriptor field = entry.getKey(); + if (field.isRepeated()) { + for (final Object element : (List)entry.getValue()) { + addRepeatedField(field, element); + } + } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + 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()); + } + } else { + setField(field, entry.getValue()); + } + } + + mergeUnknownFields(other.getUnknownFields()); + + return (BuilderType) this; + } + + @Override + public BuilderType mergeFrom(final CodedInputStream input) + throws IOException { + return mergeFrom(input, ExtensionRegistry.getEmptyRegistry()); + } + + @Override + public BuilderType mergeFrom( + final CodedInputStream input, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + final UnknownFieldSet.Builder unknownFields = + UnknownFieldSet.newBuilder(getUnknownFields()); + while (true) { + final int tag = input.readTag(); + if (tag == 0) { + break; + } + + MessageReflection.BuilderAdapter builderAdapter = + new MessageReflection.BuilderAdapter(this); + if (!MessageReflection.mergeFieldFrom(input, unknownFields, + extensionRegistry, + getDescriptorForType(), + builderAdapter, + tag)) { + // end group tag + break; + } + } + setUnknownFields(unknownFields.build()); + return (BuilderType) this; + } + + @Override + public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) { + setUnknownFields( + UnknownFieldSet.newBuilder(getUnknownFields()) + .mergeFrom(unknownFields) + .build()); + return (BuilderType) this; + } + + @Override + public Message.Builder getFieldBuilder(final FieldDescriptor field) { + throw new UnsupportedOperationException( + "getFieldBuilder() called on an unsupported message type."); + } + + @Override + public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) { + throw new UnsupportedOperationException( + "getRepeatedFieldBuilder() called on an unsupported message type."); + } + + @Override + public String toString() { + return TextFormat.printToString(this); + } + + /** + * Construct an UninitializedMessageException reporting missing fields in + * the given message. + */ + protected static UninitializedMessageException + newUninitializedMessageException(Message message) { + return new UninitializedMessageException( + MessageReflection.findMissingFields(message)); + } + + // =============================================================== + // The following definitions seem to be required in order to make javac + // not produce weird errors like: + // + // java/com/google/protobuf/DynamicMessage.java:203: types + // com.google.protobuf.AbstractMessage.Builder< + // com.google.protobuf.DynamicMessage.Builder> and + // com.google.protobuf.AbstractMessage.Builder< + // com.google.protobuf.DynamicMessage.Builder> are incompatible; both + // define mergeFrom(com.google.protobuf.ByteString), but with unrelated + // return types. + // + // Strangely, these lines are only needed if javac is invoked separately + // on AbstractMessage.java and AbstractMessageLite.java. If javac is + // invoked on both simultaneously, it works. (Or maybe the important + // point is whether or not DynamicMessage.java is compiled together with + // AbstractMessageLite.java -- not sure.) I suspect this is a compiler + // bug. + + @Override + public BuilderType mergeFrom(final ByteString data) + throws InvalidProtocolBufferException { + return (BuilderType) super.mergeFrom(data); + } + + @Override + public BuilderType mergeFrom( + final ByteString data, + final ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return (BuilderType) super.mergeFrom(data, extensionRegistry); + } + + @Override + 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) + throws InvalidProtocolBufferException { + return (BuilderType) super.mergeFrom(data, off, len); + } + + @Override + 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 ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return (BuilderType) super.mergeFrom(data, off, len, extensionRegistry); + } + + @Override + 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 { + return (BuilderType) super.mergeFrom(input, extensionRegistry); + } + + @Override + public boolean mergeDelimitedFrom(final InputStream input) + throws IOException { + return super.mergeDelimitedFrom(input); + } + + @Override + public boolean mergeDelimitedFrom( + final InputStream input, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + return super.mergeDelimitedFrom(input, extensionRegistry); + } + } +} diff --git a/java/src/main/java/com/google/protobuf/AbstractMessageLite.java b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java new file mode 100644 index 00000000..43736dd1 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java @@ -0,0 +1,386 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Collection; + +/** + * 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<MessageType, BuilderType>, + BuilderType extends AbstractMessageLite.Builder<MessageType, BuilderType>> + implements MessageLite { + protected int memoizedHashCode = 0; + + @Override + public ByteString toByteString() { + try { + final ByteString.CodedBuilder out = + ByteString.newCodedBuilder(getSerializedSize()); + writeTo(out.getCodedOutput()); + return out.build(); + } catch (IOException e) { + throw new RuntimeException( + "Serializing to a ByteString threw an IOException (should " + + "never happen).", e); + } + } + + @Override + public byte[] toByteArray() { + try { + final byte[] result = new byte[getSerializedSize()]; + final CodedOutputStream output = CodedOutputStream.newInstance(result); + writeTo(output); + output.checkNoSpaceLeft(); + return result; + } catch (IOException e) { + throw new RuntimeException( + "Serializing to a byte array threw an IOException " + + "(should never happen).", e); + } + } + + @Override + public void writeTo(final OutputStream output) throws IOException { + final int bufferSize = + CodedOutputStream.computePreferredBufferSize(getSerializedSize()); + final CodedOutputStream codedOutput = + CodedOutputStream.newInstance(output, bufferSize); + writeTo(codedOutput); + codedOutput.flush(); + } + + @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); + codedOutput.writeRawVarint32(serialized); + writeTo(codedOutput); + codedOutput.flush(); + } + + + /** + * Package private helper method for AbstractParser to create + * UninitializedMessageException. + */ + UninitializedMessageException newUninitializedMessageException() { + return new UninitializedMessageException(this); + } + + protected static void checkByteStringIsUtf8(ByteString byteString) + throws IllegalArgumentException { + if (!byteString.isValidUtf8()) { + throw new IllegalArgumentException("Byte string is not UTF-8."); + } + } + + protected static <T> void addAll(final Iterable<T> values, + final Collection<? super T> list) { + Builder.addAll(values, list); + } + + /** + * 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<MessageType, BuilderType>, + BuilderType extends Builder<MessageType, BuilderType>> + implements MessageLite.Builder { + // The compiler produces an error if this is not declared explicitly. + @Override + public abstract BuilderType clone(); + + @Override + public BuilderType mergeFrom(final CodedInputStream input) throws IOException { + return mergeFrom(input, ExtensionRegistryLite.getEmptyRegistry()); + } + + // Re-defined here for return type covariance. + @Override + public abstract BuilderType mergeFrom( + final CodedInputStream input, final ExtensionRegistryLite extensionRegistry) + throws IOException; + + @Override + public BuilderType mergeFrom(final ByteString data) throws InvalidProtocolBufferException { + try { + final CodedInputStream input = data.newCodedInput(); + mergeFrom(input); + input.checkLastTagWas(0); + return (BuilderType) this; + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "Reading from a ByteString threw an IOException (should " + + "never happen).", e); + } + } + + @Override + public BuilderType mergeFrom( + final ByteString data, final ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + try { + final CodedInputStream input = data.newCodedInput(); + mergeFrom(input, extensionRegistry); + input.checkLastTagWas(0); + return (BuilderType) this; + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "Reading from a ByteString threw an IOException (should " + + "never happen).", e); + } + } + + @Override + public BuilderType mergeFrom(final byte[] data) throws InvalidProtocolBufferException { + return mergeFrom(data, 0, data.length); + } + + @Override + public BuilderType mergeFrom(final byte[] data, final int off, final int len) + throws InvalidProtocolBufferException { + try { + final CodedInputStream input = + CodedInputStream.newInstance(data, off, len); + mergeFrom(input); + input.checkLastTagWas(0); + return (BuilderType) this; + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "Reading from a byte array threw an IOException (should " + + "never happen).", e); + } + } + + @Override + public BuilderType mergeFrom(final byte[] data, final ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return mergeFrom(data, 0, data.length, extensionRegistry); + } + + @Override + public BuilderType mergeFrom( + final byte[] data, + final int off, + final int len, + final ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + try { + final CodedInputStream input = + CodedInputStream.newInstance(data, off, len); + mergeFrom(input, extensionRegistry); + input.checkLastTagWas(0); + return (BuilderType) this; + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "Reading from a byte array threw an IOException (should " + + "never happen).", e); + } + } + + @Override + public BuilderType mergeFrom(final InputStream input) throws IOException { + final CodedInputStream codedInput = CodedInputStream.newInstance(input); + mergeFrom(codedInput); + codedInput.checkLastTagWas(0); + return (BuilderType) this; + } + + @Override + public BuilderType mergeFrom( + final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException { + final CodedInputStream codedInput = CodedInputStream.newInstance(input); + mergeFrom(codedInput, extensionRegistry); + codedInput.checkLastTagWas(0); + return (BuilderType) this; + } + + /** + * 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; + + LimitedInputStream(InputStream in, int limit) { + super(in); + this.limit = limit; + } + + @Override + public int available() throws IOException { + return Math.min(super.available(), limit); + } + + @Override + public int read() throws IOException { + if (limit <= 0) { + return -1; + } + final int result = super.read(); + if (result >= 0) { + --limit; + } + return result; + } + + @Override + public int read(final byte[] b, final int off, int len) + throws IOException { + if (limit <= 0) { + return -1; + } + len = Math.min(len, limit); + final int result = super.read(b, off, len); + if (result >= 0) { + limit -= result; + } + return result; + } + + @Override + public long skip(final long n) throws IOException { + final long result = super.skip(Math.min(n, limit)); + if (result >= 0) { + limit -= result; + } + return result; + } + } + + @Override + public boolean mergeDelimitedFrom( + final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException { + final int firstByte = input.read(); + if (firstByte == -1) { + return false; + } + final int size = CodedInputStream.readRawVarint32(firstByte, input); + final InputStream limitedInput = new LimitedInputStream(input, size); + mergeFrom(limitedInput, extensionRegistry); + return true; + } + + @Override + public boolean mergeDelimitedFrom(final InputStream input) throws IOException { + return mergeDelimitedFrom(input, + ExtensionRegistryLite.getEmptyRegistry()); + } + + @Override + @SuppressWarnings("unchecked") // isInstance takes care of this + public BuilderType mergeFrom(final MessageLite other) { + if (!getDefaultInstanceForType().getClass().isInstance(other)) { + throw new IllegalArgumentException( + "mergeFrom(MessageLite) can only merge messages of the same type."); + } + + return internalMergeFrom((MessageType) other); + } + + protected abstract BuilderType internalMergeFrom(MessageType message); + + /** + * Construct an UninitializedMessageException reporting missing fields in + * the given message. + */ + protected static UninitializedMessageException + newUninitializedMessageException(MessageLite message) { + return new UninitializedMessageException(message); + } + + /** + * Adds the {@code values} to the {@code list}. This is a helper method + * used by generated code. Users should ignore it. + * + * @throws NullPointerException if {@code values} or any of the elements of + * {@code values} is null. When that happens, some elements of + * {@code values} may have already been added to the result {@code list}. + */ + protected static <T> void addAll(final Iterable<T> values, + final Collection<? super T> list) { + if (values == null) { + throw new NullPointerException(); + } + if (values instanceof LazyStringList) { + // For StringOrByteStringLists, check the underlying elements to avoid + // forcing conversions of ByteStrings to Strings. + checkForNullValues(((LazyStringList) values).getUnderlyingElements()); + list.addAll((Collection<T>) values); + } else if (values instanceof Collection) { + checkForNullValues(values); + list.addAll((Collection<T>) values); + } else { + for (final T value : values) { + if (value == null) { + throw new NullPointerException(); + } + list.add(value); + } + } + } + + private static void checkForNullValues(final Iterable<?> values) { + for (final Object value : values) { + if (value == null) { + throw new NullPointerException(); + } + } + } + } +} diff --git a/java/src/main/java/com/google/protobuf/AbstractParser.java b/java/src/main/java/com/google/protobuf/AbstractParser.java new file mode 100644 index 00000000..66b0ee3b --- /dev/null +++ b/java/src/main/java/com/google/protobuf/AbstractParser.java @@ -0,0 +1,258 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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.AbstractMessageLite.Builder.LimitedInputStream; + +import java.io.IOException; +import java.io.InputStream; + +/** + * 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)} + * + * @author liujisi@google.com (Pherl Liu) + */ +public abstract class AbstractParser<MessageType extends MessageLite> + implements Parser<MessageType> { + /** + * Creates an UninitializedMessageException for MessageType. + */ + private UninitializedMessageException + newUninitializedMessageException(MessageType message) { + if (message instanceof AbstractMessageLite) { + return ((AbstractMessageLite) message).newUninitializedMessageException(); + } + return new UninitializedMessageException(message); + } + + /** + * Helper method to check if message is initialized. + * + * @throws InvalidProtocolBufferException if it is not initialized. + * @return The message to check. + */ + private MessageType checkMessageInitialized(MessageType message) + throws InvalidProtocolBufferException { + if (message != null && !message.isInitialized()) { + throw newUninitializedMessageException(message) + .asInvalidProtocolBufferException() + .setUnfinishedMessage(message); + } + return message; + } + + private static final ExtensionRegistryLite EMPTY_REGISTRY + = ExtensionRegistryLite.getEmptyRegistry(); + + @Override + public MessageType parsePartialFrom(CodedInputStream input) + throws InvalidProtocolBufferException { + return parsePartialFrom(input, EMPTY_REGISTRY); + } + + @Override + public MessageType parseFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return checkMessageInitialized( + parsePartialFrom(input, extensionRegistry)); + } + + @Override + public MessageType parseFrom(CodedInputStream input) throws InvalidProtocolBufferException { + return parseFrom(input, EMPTY_REGISTRY); + } + + @Override + public MessageType parsePartialFrom(ByteString data, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + MessageType message; + try { + CodedInputStream input = data.newCodedInput(); + message = parsePartialFrom(input, extensionRegistry); + try { + input.checkLastTagWas(0); + } catch (InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(message); + } + return message; + } catch (InvalidProtocolBufferException e) { + throw e; + } + } + + @Override + public MessageType parsePartialFrom(ByteString data) throws InvalidProtocolBufferException { + return parsePartialFrom(data, EMPTY_REGISTRY); + } + + @Override + public MessageType parseFrom(ByteString data, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return checkMessageInitialized(parsePartialFrom(data, extensionRegistry)); + } + + @Override + public MessageType parseFrom(ByteString data) throws InvalidProtocolBufferException { + return parseFrom(data, EMPTY_REGISTRY); + } + + @Override + public MessageType parsePartialFrom( + byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + try { + CodedInputStream input = CodedInputStream.newInstance(data, off, len); + MessageType message = parsePartialFrom(input, extensionRegistry); + try { + input.checkLastTagWas(0); + } catch (InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(message); + } + return message; + } catch (InvalidProtocolBufferException e) { + throw e; + } + } + + @Override + public MessageType parsePartialFrom(byte[] data, int off, int len) + throws InvalidProtocolBufferException { + return parsePartialFrom(data, off, len, EMPTY_REGISTRY); + } + + @Override + public MessageType parsePartialFrom(byte[] data, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return parsePartialFrom(data, 0, data.length, extensionRegistry); + } + + @Override + public MessageType parsePartialFrom(byte[] data) throws InvalidProtocolBufferException { + return parsePartialFrom(data, 0, data.length, EMPTY_REGISTRY); + } + + @Override + public MessageType parseFrom( + byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return checkMessageInitialized( + parsePartialFrom(data, off, len, extensionRegistry)); + } + + @Override + public MessageType parseFrom(byte[] data, int off, int len) + throws InvalidProtocolBufferException { + return parseFrom(data, off, len, EMPTY_REGISTRY); + } + + @Override + public MessageType parseFrom(byte[] data, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return parseFrom(data, 0, data.length, extensionRegistry); + } + + @Override + public MessageType parseFrom(byte[] data) throws InvalidProtocolBufferException { + return parseFrom(data, EMPTY_REGISTRY); + } + + @Override + public MessageType parsePartialFrom(InputStream input, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + CodedInputStream codedInput = CodedInputStream.newInstance(input); + MessageType message = parsePartialFrom(codedInput, extensionRegistry); + try { + codedInput.checkLastTagWas(0); + } catch (InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(message); + } + return message; + } + + @Override + public MessageType parsePartialFrom(InputStream input) throws InvalidProtocolBufferException { + return parsePartialFrom(input, EMPTY_REGISTRY); + } + + @Override + public MessageType parseFrom(InputStream input, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return checkMessageInitialized( + parsePartialFrom(input, extensionRegistry)); + } + + @Override + public MessageType parseFrom(InputStream input) throws InvalidProtocolBufferException { + return parseFrom(input, EMPTY_REGISTRY); + } + + @Override + public MessageType parsePartialDelimitedFrom( + InputStream input, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + int size; + try { + int firstByte = input.read(); + if (firstByte == -1) { + return null; + } + size = CodedInputStream.readRawVarint32(firstByte, input); + } catch (IOException e) { + throw new InvalidProtocolBufferException(e.getMessage()); + } + InputStream limitedInput = new LimitedInputStream(input, size); + return parsePartialFrom(limitedInput, extensionRegistry); + } + + @Override + public MessageType parsePartialDelimitedFrom(InputStream input) + throws InvalidProtocolBufferException { + return parsePartialDelimitedFrom(input, EMPTY_REGISTRY); + } + + @Override + public MessageType parseDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return checkMessageInitialized( + parsePartialDelimitedFrom(input, extensionRegistry)); + } + + @Override + public MessageType parseDelimitedFrom(InputStream input) throws InvalidProtocolBufferException { + return parseDelimitedFrom(input, EMPTY_REGISTRY); + } +} diff --git a/java/src/main/java/com/google/protobuf/AbstractProtobufList.java b/java/src/main/java/com/google/protobuf/AbstractProtobufList.java new file mode 100644 index 00000000..b17db6e0 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/AbstractProtobufList.java @@ -0,0 +1,180 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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.AbstractList; +import java.util.Collection; +import java.util.List; +import java.util.RandomAccess; + +/** + * 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. + * <p> + * This implementation assumes all subclasses are array based, supporting random access. + */ +abstract class AbstractProtobufList<E> extends AbstractList<E> implements ProtobufList<E> { + + protected static final int DEFAULT_CAPACITY = 10; + + /** + * Whether or not this list is modifiable. + */ + private boolean isMutable; + + /** + * Constructs a mutable list by default. + */ + AbstractProtobufList() { + isMutable = true; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof List)) { + return false; + } + // Handle lists that do not support RandomAccess as efficiently as possible by using an iterator + // based approach in our super class. Otherwise our index based approach will avoid those + // allocations. + if (!(o instanceof RandomAccess)) { + return super.equals(o); + } + + List<?> other = (List<?>) o; + final int size = size(); + if (size != other.size()) { + return false; + } + for (int i = 0; i < size; i++) { + if (!get(i).equals(other.get(i))) { + return false; + } + } + return true; + } + + @Override + public int hashCode() { + final int size = size(); + int hashCode = 1; + for (int i = 0; i < size; i++) { + hashCode = (31 * hashCode) + get(i).hashCode(); + } + return hashCode; + } + + @Override + public boolean add(E e) { + ensureIsMutable(); + return super.add(e); + } + + @Override + public void add(int index, E element) { + ensureIsMutable(); + super.add(index, element); + } + + @Override + public boolean addAll(Collection<? extends E> c) { + ensureIsMutable(); + return super.addAll(c); + } + + @Override + public boolean addAll(int index, Collection<? extends E> c) { + ensureIsMutable(); + return super.addAll(index, c); + } + + @Override + 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); + } + + @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. + */ + protected void ensureIsMutable() { + if (!isMutable) { + throw new UnsupportedOperationException(); + } + } +} diff --git a/java/src/main/java/com/google/protobuf/BlockingRpcChannel.java b/java/src/main/java/com/google/protobuf/BlockingRpcChannel.java new file mode 100644 index 00000000..d535efb9 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/BlockingRpcChannel.java @@ -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. + +package com.google.protobuf; + +/** + * <p>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}. + */ + Message callBlockingMethod( + Descriptors.MethodDescriptor method, + RpcController controller, + Message request, + Message responsePrototype) throws ServiceException; +} diff --git a/java/src/main/java/com/google/protobuf/BlockingService.java b/java/src/main/java/com/google/protobuf/BlockingService.java new file mode 100644 index 00000000..d01f0b8f --- /dev/null +++ b/java/src/main/java/com/google/protobuf/BlockingService.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; + +/** + * Blocking equivalent to {@link Service}. + * + * @author kenton@google.com Kenton Varda + * @author cpovirk@google.com Chris Povirk + */ +public interface BlockingService { + /** + * 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. + */ + Message callBlockingMethod(Descriptors.MethodDescriptor method, + RpcController controller, + Message request) throws ServiceException; + + /** + * Equivalent to {@link Service#getRequestPrototype}. + */ + Message getRequestPrototype(Descriptors.MethodDescriptor method); + + /** + * Equivalent to {@link Service#getResponsePrototype}. + */ + Message getResponsePrototype(Descriptors.MethodDescriptor method); +} 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 d6a2f6fa..668d65ab 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 @@ -264,7 +264,11 @@ class FieldMaskTree { } } } else { - destination.setField(field, source.getField(field)); + if (source.hasField(field) || !options.replacePrimitiveFields()) { + destination.setField(field, source.getField(field)); + } else { + destination.clearField(field); + } } } } 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 0b3060a7..96961521 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 @@ -211,14 +211,19 @@ public class FieldMaskUtil { public static FieldMask normalize(FieldMask mask) { return new FieldMaskTree(mask).toFieldMask(); } - + /** - * Creates an union of two FieldMasks. + * Creates a union of two or more FieldMasks. */ - public static FieldMask union(FieldMask mask1, FieldMask mask2) { - return new FieldMaskTree(mask1).mergeFromFieldMask(mask2).toFieldMask(); + public static FieldMask union( + FieldMask firstMask, FieldMask secondMask, FieldMask... otherMasks) { + FieldMaskTree maskTree = new FieldMaskTree(firstMask).mergeFromFieldMask(secondMask); + for (FieldMask mask : otherMasks) { + maskTree.mergeFromFieldMask(mask); + } + return maskTree.toFieldMask(); } - + /** * Calculates the intersection of two FieldMasks. */ @@ -237,6 +242,9 @@ public class FieldMaskUtil { public static final class MergeOptions { private boolean replaceMessageFields = false; private boolean replaceRepeatedFields = false; + // TODO(b/28277137): change the default behavior to always replace primitive fields after + // fixing all failing TAP tests. + private boolean replacePrimitiveFields = false; /** * Whether to replace message fields (i.e., discard existing content in @@ -257,7 +265,23 @@ public class FieldMaskUtil { public boolean replaceRepeatedFields() { return 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. + * + * <p>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 boolean replacePrimitiveFields() { + return replacePrimitiveFields; + } + public void setReplaceMessageFields(boolean value) { replaceMessageFields = value; } @@ -265,10 +289,15 @@ public class FieldMaskUtil { public void setReplaceRepeatedFields(boolean value) { replaceRepeatedFields = value; } + + public void setReplacePrimitiveFields(boolean value) { + replacePrimitiveFields = value; + } } - + /** - * Merges fields specified by a FieldMask from one message to another. + * Merges fields specified by a FieldMask from one message to another with the + * specified merge options. */ public static void merge(FieldMask mask, Message source, Message.Builder destination, MergeOptions options) { 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 618e0072..3ee0fc6e 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 @@ -237,5 +237,25 @@ public class FieldMaskTreeTest extends TestCase { builder.getPayloadBuilder().setOptionalUint32(2000); new FieldMaskTree().addFieldPath("payload").merge(clearedSource, builder, options); assertEquals(false, builder.hasPayload()); + + // Test merging unset primitive fields. + builder = source.toBuilder(); + builder.getPayloadBuilder().clearOptionalInt32(); + NestedTestAllTypes sourceWithPayloadInt32Unset = builder.build(); + builder = source.toBuilder(); + new FieldMaskTree() + .addFieldPath("payload.optional_int32") + .merge(sourceWithPayloadInt32Unset, builder, options); + 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); + 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 a312fc33..194f7b9c 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 @@ -152,6 +152,15 @@ public class FieldMaskUtilTest extends TestCase { FieldMask result = FieldMaskUtil.union(mask1, mask2); assertEquals("bar,foo", FieldMaskUtil.toString(result)); } + + public void testUnion_usingVarArgs() throws Exception { + FieldMask mask1 = FieldMaskUtil.fromString("foo"); + FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar.quz"); + FieldMask mask3 = FieldMaskUtil.fromString("bar.quz"); + FieldMask mask4 = FieldMaskUtil.fromString("bar"); + FieldMask result = FieldMaskUtil.union(mask1, mask2, mask3, mask4); + assertEquals("bar,foo", FieldMaskUtil.toString(result)); + } public void testIntersection() throws Exception { // Only test a simple case here and expect diff --git a/js/binary/utils.js b/js/binary/utils.js index 875ff955..51405553 100644 --- a/js/binary/utils.js +++ b/js/binary/utils.js @@ -568,6 +568,56 @@ jspb.utils.hash64ArrayToDecimalStrings = function(hashes, signed) { /** + * Converts a signed or unsigned decimal string into its hash string + * representation. + * @param {string} dec + * @return {string} + */ +jspb.utils.decimalStringToHash64 = function(dec) { + goog.asserts.assert(dec.length > 0); + + // Check for minus sign. + var minus = false; + if (dec[0] === '-') { + minus = true; + dec = dec.slice(1); + } + + // Store result as a byte array. + var resultBytes = [0, 0, 0, 0, 0, 0, 0, 0]; + + // Set result to m*result + c. + function muladd(m, c) { + for (var i = 0; i < 8 && (m !== 1 || c > 0); i++) { + var r = m * resultBytes[i] + c; + resultBytes[i] = r & 0xFF; + c = r >>> 8; + } + } + + // Negate the result bits. + function neg() { + for (var i = 0; i < 8; i++) { + resultBytes[i] = (~resultBytes[i]) & 0xFF; + } + } + + // 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])); + } + + // If there's a minus sign, convert into two's complement. + if (minus) { + neg(); + muladd(1, 1); + } + + return String.fromCharCode.apply(null, resultBytes); +}; + + +/** * Converts an 8-character hash string into its hexadecimal representation. * @param {string} hash * @return {string} diff --git a/js/binary/utils_test.js b/js/binary/utils_test.js index 518d7597..d27e5ea2 100644 --- a/js/binary/utils_test.js +++ b/js/binary/utils_test.js @@ -197,6 +197,41 @@ describe('binaryUtilsTest', function() { assertEquals('123456789123456789', result[2]); }); + /* + * Going from decimal strings to hash strings should be lossless. + */ + it('testDecimalToHashConversion', function() { + var result; + var convert = jspb.utils.decimalStringToHash64; + + result = convert('0'); + assertEquals(String.fromCharCode.apply(null, + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), result); + + result = convert('-1'); + assertEquals(String.fromCharCode.apply(null, + [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result); + + result = convert('18446744073709551615'); + assertEquals(String.fromCharCode.apply(null, + [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result); + + result = convert('9223372036854775808'); + assertEquals(String.fromCharCode.apply(null, + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result); + + result = convert('-9223372036854775808'); + assertEquals(String.fromCharCode.apply(null, + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result); + + result = convert('123456789123456789'); + assertEquals(String.fromCharCode.apply(null, + [0x15, 0x5F, 0xD0, 0xAC, 0x4B, 0x9B, 0xB6, 0x01]), result); + + result = convert('-123456789123456789'); + assertEquals(String.fromCharCode.apply(null, + [0xEB, 0xA0, 0x2F, 0x53, 0xB4, 0x64, 0x49, 0xFE]), result); + }); /** * Going from hash strings to hex strings should be lossless. diff --git a/js/gulpfile.js b/js/gulpfile.js index 7e44aa76..c5220153 100644 --- a/js/gulpfile.js +++ b/js/gulpfile.js @@ -1,7 +1,11 @@ var gulp = require('gulp'); -var exec = require('child_process').exec; +var execFile = require('child_process').execFile; var glob = require('glob'); +function exec(command, cb) { + execFile('sh', ['-c', command], cb); +} + var protoc = process.env.PROTOC || '../src/protoc'; gulp.task('genproto_closure', function (cb) { diff --git a/js/package.json b/js/package.json index 6418e507..c16417ca 100644 --- a/js/package.json +++ b/js/package.json @@ -13,7 +13,7 @@ "glob": "~6.0.4" }, "scripts": { - "test": "./node_modules/gulp/bin/gulp.js test" + "test": "node ./node_modules/gulp/bin/gulp.js test" }, "repository": { "type": "git", diff --git a/objectivec/DevTools/full_mac_build.sh b/objectivec/DevTools/full_mac_build.sh index 4d4930dc..ff51d9f0 100755 --- a/objectivec/DevTools/full_mac_build.sh +++ b/objectivec/DevTools/full_mac_build.sh @@ -26,8 +26,9 @@ OPTIONS: Issue a clean before the normal build. -a, --autogen Start by rerunning autogen & configure. - -r, --regenerate-cpp-descriptors - The descriptor.proto is checked in generated, cause it to regenerate. + -r, --regenerate-descriptors + Run generate_descriptor_proto.sh to regenerate all the checked in + proto sources. -j #, --jobs # Force the number of parallel jobs (useful for debugging build issues). --core-only @@ -71,7 +72,7 @@ fi DO_AUTOGEN=no DO_CLEAN=no -REGEN_CPP_DESCRIPTORS=no +REGEN_DESCRIPTORS=no CORE_ONLY=no DO_XCODE_IOS_TESTS=yes DO_XCODE_OSX_TESTS=yes @@ -88,8 +89,8 @@ while [[ $# != 0 ]]; do -a | --autogen ) DO_AUTOGEN=yes ;; - -r | --regenerate-cpp-descriptors ) - REGEN_CPP_DESCRIPTORS=yes + -r | --regenerate-descriptors ) + REGEN_DESCRIPTORS=yes ;; -j | --jobs ) shift @@ -164,8 +165,8 @@ if [[ "${DO_CLEAN}" == "yes" ]] ; then fi fi -if [[ "${REGEN_CPP_DESCRIPTORS}" == "yes" ]] ; then - header "Regenerating the C++ descriptor sources." +if [[ "${REGEN_DESCRIPTORS}" == "yes" ]] ; then + header "Regenerating the descriptor sources." ./generate_descriptor_proto.sh -j "${NUM_MAKE_JOBS}" fi @@ -184,29 +185,8 @@ else cd .. fi -header "Ensuring the ObjC descriptors are current." -# Find the newest input file (protos, compiler, and the generator script). -# (these patterns catch some extra stuff, but better to over sample than under) -readonly NewestInput=$(find \ - src/google/protobuf/*.proto \ - src/.libs src/*.la src/protoc \ - objectivec/generate_well_known_types.sh \ - -type f -print0 \ - | xargs -0 stat -f "%m %N" \ - | sort -n | tail -n1 | cut -f2- -d" ") -# Find the oldest output file. -readonly OldestOutput=$(find \ - "${ProtoRootDir}/objectivec/google" \ - -type f -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. -if [[ "${NewestInput}" -nt "${OldestOutput}" ]] ; then - echo ">> Newest input is newer than oldest output, regenerating." - objectivec/generate_well_known_types.sh -j "${NUM_MAKE_JOBS}" -else - echo ">> Newest input is older than oldest output, no need to regenerating." -fi +# Ensure the WKT sources checked in are current. +objectivec/generate_well_known_types.sh --check-only -j "${NUM_MAKE_JOBS}" header "Checking on the ObjC Runtime Code" objectivec/DevTools/pddm_tests.py diff --git a/objectivec/GPBCodedOutputStream.h b/objectivec/GPBCodedOutputStream.h index e67efd2d..8272880d 100644 --- a/objectivec/GPBCodedOutputStream.h +++ b/objectivec/GPBCodedOutputStream.h @@ -112,7 +112,7 @@ NS_ASSUME_NONNULL_BEGIN /// Write a double for the given field number. - (void)writeDouble:(int32_t)fieldNumber value:(double)value; -/// Write a packaged array of double for the given field number. +/// Write a packed array of double for the given field number. - (void)writeDoubleArray:(int32_t)fieldNumber values:(GPBDoubleArray *)values tag:(uint32_t)tag; @@ -121,7 +121,7 @@ NS_ASSUME_NONNULL_BEGIN /// Write a float for the given field number. - (void)writeFloat:(int32_t)fieldNumber value:(float)value; -/// Write a packaged array of float for the given field number. +/// Write a packed array of float for the given field number. - (void)writeFloatArray:(int32_t)fieldNumber values:(GPBFloatArray *)values tag:(uint32_t)tag; @@ -130,7 +130,7 @@ NS_ASSUME_NONNULL_BEGIN /// Write a uint64_t for the given field number. - (void)writeUInt64:(int32_t)fieldNumber value:(uint64_t)value; -/// Write a packaged array of uint64_t for the given field number. +/// Write a packed array of uint64_t for the given field number. - (void)writeUInt64Array:(int32_t)fieldNumber values:(GPBUInt64Array *)values tag:(uint32_t)tag; @@ -139,7 +139,7 @@ NS_ASSUME_NONNULL_BEGIN /// Write a int64_t for the given field number. - (void)writeInt64:(int32_t)fieldNumber value:(int64_t)value; -/// Write a packaged array of int64_t for the given field number. +/// Write a packed array of int64_t for the given field number. - (void)writeInt64Array:(int32_t)fieldNumber values:(GPBInt64Array *)values tag:(uint32_t)tag; @@ -148,7 +148,7 @@ NS_ASSUME_NONNULL_BEGIN /// Write a int32_t for the given field number. - (void)writeInt32:(int32_t)fieldNumber value:(int32_t)value; -/// Write a packaged array of int32_t for the given field number. +/// Write a packed array of int32_t for the given field number. - (void)writeInt32Array:(int32_t)fieldNumber values:(GPBInt32Array *)values tag:(uint32_t)tag; @@ -157,7 +157,7 @@ NS_ASSUME_NONNULL_BEGIN /// Write a uint32_t for the given field number. - (void)writeUInt32:(int32_t)fieldNumber value:(uint32_t)value; -/// Write a packaged array of uint32_t for the given field number. +/// Write a packed array of uint32_t for the given field number. - (void)writeUInt32Array:(int32_t)fieldNumber values:(GPBUInt32Array *)values tag:(uint32_t)tag; @@ -166,7 +166,7 @@ NS_ASSUME_NONNULL_BEGIN /// Write a uint64_t for the given field number. - (void)writeFixed64:(int32_t)fieldNumber value:(uint64_t)value; -/// Write a packaged array of uint64_t for the given field number. +/// Write a packed array of uint64_t for the given field number. - (void)writeFixed64Array:(int32_t)fieldNumber values:(GPBUInt64Array *)values tag:(uint32_t)tag; @@ -175,7 +175,7 @@ NS_ASSUME_NONNULL_BEGIN /// Write a uint32_t for the given field number. - (void)writeFixed32:(int32_t)fieldNumber value:(uint32_t)value; -/// Write a packaged array of uint32_t for the given field number. +/// Write a packed array of uint32_t for the given field number. - (void)writeFixed32Array:(int32_t)fieldNumber values:(GPBUInt32Array *)values tag:(uint32_t)tag; @@ -184,7 +184,7 @@ NS_ASSUME_NONNULL_BEGIN /// Write a int32_t for the given field number. - (void)writeSInt32:(int32_t)fieldNumber value:(int32_t)value; -/// Write a packaged array of int32_t for the given field number. +/// Write a packed array of int32_t for the given field number. - (void)writeSInt32Array:(int32_t)fieldNumber values:(GPBInt32Array *)values tag:(uint32_t)tag; @@ -193,7 +193,7 @@ NS_ASSUME_NONNULL_BEGIN /// Write a int64_t for the given field number. - (void)writeSInt64:(int32_t)fieldNumber value:(int64_t)value; -/// Write a packaged array of int64_t for the given field number. +/// Write a packed array of int64_t for the given field number. - (void)writeSInt64Array:(int32_t)fieldNumber values:(GPBInt64Array *)values tag:(uint32_t)tag; @@ -202,7 +202,7 @@ NS_ASSUME_NONNULL_BEGIN /// Write a int64_t for the given field number. - (void)writeSFixed64:(int32_t)fieldNumber value:(int64_t)value; -/// Write a packaged array of int64_t for the given field number. +/// Write a packed array of int64_t for the given field number. - (void)writeSFixed64Array:(int32_t)fieldNumber values:(GPBInt64Array *)values tag:(uint32_t)tag; @@ -211,7 +211,7 @@ NS_ASSUME_NONNULL_BEGIN /// Write a int32_t for the given field number. - (void)writeSFixed32:(int32_t)fieldNumber value:(int32_t)value; -/// Write a packaged array of int32_t for the given field number. +/// Write a packed array of int32_t for the given field number. - (void)writeSFixed32Array:(int32_t)fieldNumber values:(GPBInt32Array *)values tag:(uint32_t)tag; @@ -220,7 +220,7 @@ NS_ASSUME_NONNULL_BEGIN /// Write a BOOL for the given field number. - (void)writeBool:(int32_t)fieldNumber value:(BOOL)value; -/// Write a packaged array of BOOL for the given field number. +/// Write a packed array of BOOL for the given field number. - (void)writeBoolArray:(int32_t)fieldNumber values:(GPBBoolArray *)values tag:(uint32_t)tag; @@ -229,7 +229,7 @@ NS_ASSUME_NONNULL_BEGIN /// Write a int32_t for the given field number. - (void)writeEnum:(int32_t)fieldNumber value:(int32_t)value; -/// Write a packaged array of int32_t for the given field number. +/// Write a packed array of int32_t for the given field number. - (void)writeEnumArray:(int32_t)fieldNumber values:(GPBEnumArray *)values tag:(uint32_t)tag; @@ -293,7 +293,7 @@ NS_ASSUME_NONNULL_END //%PDDM-DEFINE _WRITE_PACKABLE_DECLS(NAME, ARRAY_TYPE, TYPE) //%/// Write a TYPE for the given field number. //%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE)value; -//%/// Write a packaged array of TYPE for the given field number. +//%/// Write a packed array of TYPE for the given field number. //%- (void)write##NAME##Array:(int32_t)fieldNumber //% NAME$S values:(GPB##ARRAY_TYPE##Array *)values //% NAME$S tag:(uint32_t)tag; diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m index 0e1599dc..8134e259 100644 --- a/objectivec/GPBMessage.m +++ b/objectivec/GPBMessage.m @@ -2603,9 +2603,13 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream( size_t fieldOffset = field->description_->offset; switch (fieldDataType) { case GPBDataTypeBool: { - BOOL *selfValPtr = (BOOL *)&selfStorage[fieldOffset]; - BOOL *otherValPtr = (BOOL *)&otherStorage[fieldOffset]; - if (*selfValPtr != *otherValPtr) { + // Bools are stored in has_bits to avoid needing explicit space in + // the storage structure. + // (the field number passed to the HasIvar helper doesn't really + // matter since the offset is never negative) + BOOL selfValue = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0); + BOOL otherValue = GPBGetHasIvar(other, (int32_t)(fieldOffset), 0); + if (selfValue != otherValue) { return NO; } break; @@ -2714,8 +2718,12 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream( size_t fieldOffset = field->description_->offset; switch (fieldDataType) { case GPBDataTypeBool: { - BOOL *valPtr = (BOOL *)&storage[fieldOffset]; - result = prime * result + *valPtr; + // Bools are stored in has_bits to avoid needing explicit space in + // the storage structure. + // (the field number passed to the HasIvar helper doesn't really + // matter since the offset is never negative) + BOOL value = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0); + result = prime * result + value; break; } case GPBDataTypeSFixed32: diff --git a/objectivec/Tests/GPBMessageTests.m b/objectivec/Tests/GPBMessageTests.m index 43546156..89d1fce2 100644 --- a/objectivec/Tests/GPBMessageTests.m +++ b/objectivec/Tests/GPBMessageTests.m @@ -1947,4 +1947,76 @@ EnumTestMsg_MyEnum_NegTwo); } +- (void)testOneBasedEnumHolder { + // Test case for https://github.com/google/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); +} + +- (void)testBoolOffsetUsage { + // Bools use storage within has_bits; this test ensures that this is honored + // in all places where things should crash or fail based on reading out of + // field storage instead. + BoolOnlyMessage *msg1 = [BoolOnlyMessage message]; + BoolOnlyMessage *msg2 = [BoolOnlyMessage message]; + + msg1.boolField1 = YES; + msg2.boolField1 = YES; + msg1.boolField3 = YES; + msg2.boolField3 = YES; + msg1.boolField5 = YES; + msg2.boolField5 = YES; + msg1.boolField7 = YES; + msg2.boolField7 = YES; + msg1.boolField9 = YES; + msg2.boolField9 = YES; + msg1.boolField11 = YES; + msg2.boolField11 = YES; + msg1.boolField13 = YES; + msg2.boolField13 = YES; + msg1.boolField15 = YES; + msg2.boolField15 = YES; + msg1.boolField17 = YES; + msg2.boolField17 = YES; + msg1.boolField19 = YES; + msg2.boolField19 = YES; + msg1.boolField21 = YES; + msg2.boolField21 = YES; + msg1.boolField23 = YES; + msg2.boolField23 = YES; + msg1.boolField25 = YES; + msg2.boolField25 = YES; + msg1.boolField27 = YES; + msg2.boolField27 = YES; + msg1.boolField29 = YES; + msg2.boolField29 = YES; + msg1.boolField31 = YES; + msg2.boolField31 = YES; + + msg1.boolField32 = YES; + msg2.boolField32 = YES; + + XCTAssertTrue(msg1 != msg2); // Different pointers. + XCTAssertEqual([msg1 hash], [msg2 hash]); + XCTAssertEqualObjects(msg1, msg2); + + BoolOnlyMessage *msg1Prime = [[msg1 copy] autorelease]; + XCTAssertTrue(msg1Prime != msg1); // Different pointers. + XCTAssertEqual([msg1 hash], [msg1Prime hash]); + XCTAssertEqualObjects(msg1, msg1Prime); + + // Field set in one, but not the other means they don't match (even if + // set to default value). + msg1Prime.boolField2 = NO; + XCTAssertNotEqualObjects(msg1Prime, msg1); + // And when set to different values. + msg1.boolField2 = YES; + XCTAssertNotEqualObjects(msg1Prime, msg1); + // And then they match again. + msg1.boolField2 = NO; + XCTAssertEqualObjects(msg1Prime, msg1); + XCTAssertEqual([msg1 hash], [msg1Prime hash]); +} + @end diff --git a/objectivec/Tests/unittest_objc.proto b/objectivec/Tests/unittest_objc.proto index 9483cb1d..f6ab6a24 100644 --- a/objectivec/Tests/unittest_objc.proto +++ b/objectivec/Tests/unittest_objc.proto @@ -401,3 +401,49 @@ message EnumTestMsg { repeated MyEnum mumble = 4; } + +// Test case for https://github.com/google/protobuf/issues/1453 +// Message with no explicit defaults, but a non zero default for an enum. +message MessageWithOneBasedEnum { + enum OneBasedEnum { + ONE = 1; + TWO = 2; + } + optional OneBasedEnum enum_field = 1; +} + +// Message with all bools for testing things related to bool storage. +message BoolOnlyMessage { + optional bool bool_field_1 = 1; + optional bool bool_field_2 = 2; + optional bool bool_field_3 = 3; + optional bool bool_field_4 = 4; + optional bool bool_field_5 = 5; + optional bool bool_field_6 = 6; + optional bool bool_field_7 = 7; + optional bool bool_field_8 = 8; + optional bool bool_field_9 = 9; + optional bool bool_field_10 = 10; + optional bool bool_field_11 = 11; + optional bool bool_field_12 = 12; + optional bool bool_field_13 = 13; + optional bool bool_field_14 = 14; + optional bool bool_field_15 = 15; + optional bool bool_field_16 = 16; + optional bool bool_field_17 = 17; + optional bool bool_field_18 = 18; + optional bool bool_field_19 = 19; + optional bool bool_field_20 = 20; + optional bool bool_field_21 = 21; + optional bool bool_field_22 = 22; + optional bool bool_field_23 = 23; + optional bool bool_field_24 = 24; + optional bool bool_field_25 = 25; + optional bool bool_field_26 = 26; + optional bool bool_field_27 = 27; + optional bool bool_field_28 = 28; + optional bool bool_field_29 = 29; + optional bool bool_field_30 = 30; + optional bool bool_field_31 = 31; + optional bool bool_field_32 = 32; +} diff --git a/objectivec/generate_well_known_types.sh b/objectivec/generate_well_known_types.sh index be9b38a5..36c34603 100755 --- a/objectivec/generate_well_known_types.sh +++ b/objectivec/generate_well_known_types.sh @@ -12,6 +12,13 @@ set -eu readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")") readonly ProtoRootDir="${ScriptDir}/.." +# Flag for continuous integration to check that everything is current. +CHECK_ONLY=0 +if [[ $# -ge 1 && ( "$1" == "--check-only" ) ]] ; then + CHECK_ONLY=1 + shift +fi + pushd "${ProtoRootDir}" > /dev/null if test ! -e src/google/protobuf/stubs/common.h; then @@ -46,4 +53,24 @@ declare -a RUNTIME_PROTO_FILES=( \ google/protobuf/type.proto \ google/protobuf/wrappers.proto) -./protoc --objc_out="${ProtoRootDir}/objectivec" ${RUNTIME_PROTO_FILES[@]} +# 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 + +# Copy them over. +echo "Copying over updated WellKnownType sources." +cp -r "${TMP_DIR}/google/." "${ProtoRootDir}/objectivec/google/" diff --git a/objectivec/google/protobuf/Any.pbobjc.h b/objectivec/google/protobuf/Any.pbobjc.h index 79ec0fb7..4002a989 100644 --- a/objectivec/google/protobuf/Any.pbobjc.h +++ b/objectivec/google/protobuf/Any.pbobjc.h @@ -9,6 +9,9 @@ // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + CF_EXTERN_C_BEGIN NS_ASSUME_NONNULL_BEGIN @@ -33,8 +36,36 @@ typedef GPB_ENUM(GPBAny_FieldNumber) { GPBAny_FieldNumber_Value = 2, }; -/// `Any` contains an arbitrary serialized message along with a URL -/// that describes the type of the serialized message. +/// `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); +/// } +/// +/// 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 @@ -67,7 +98,7 @@ typedef GPB_ENUM(GPBAny_FieldNumber) { @interface GPBAny : GPBMessage /// A URL/resource name whose content describes the type of the -/// serialized message. +/// serialized protocol buffer message. /// /// For URLs which use the schema `http`, `https`, or no schema, the /// following restrictions and interpretations apply: @@ -75,6 +106,8 @@ typedef GPB_ENUM(GPBAny_FieldNumber) { /// * If no schema 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 @@ -87,7 +120,7 @@ typedef GPB_ENUM(GPBAny_FieldNumber) { /// used with implementation specific semantics. @property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL; -/// Must be valid serialized data of the above specified type. +/// Must be a valid serialized protocol buffer of the above specified type. @property(nonatomic, readwrite, copy, null_resettable) NSData *value; @end @@ -96,4 +129,6 @@ NS_ASSUME_NONNULL_END CF_EXTERN_C_END +#pragma clang diagnostic pop + // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Any.pbobjc.m b/objectivec/google/protobuf/Any.pbobjc.m index 7cbf0def..6a1bf894 100644 --- a/objectivec/google/protobuf/Any.pbobjc.m +++ b/objectivec/google/protobuf/Any.pbobjc.m @@ -5,6 +5,9 @@ #import "google/protobuf/Any.pbobjc.h" // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + #pragma mark - GPBAnyRoot @implementation GPBAnyRoot @@ -85,4 +88,6 @@ typedef struct GPBAny__storage_ { @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 3f7e99c6..d66df629 100644 --- a/objectivec/google/protobuf/Api.pbobjc.h +++ b/objectivec/google/protobuf/Api.pbobjc.h @@ -9,6 +9,9 @@ // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + CF_EXTERN_C_BEGIN @class GPBMethod; @@ -254,4 +257,6 @@ NS_ASSUME_NONNULL_END CF_EXTERN_C_END +#pragma clang diagnostic pop + // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Api.pbobjc.m b/objectivec/google/protobuf/Api.pbobjc.m index 2b2f62ea..45a06e60 100644 --- a/objectivec/google/protobuf/Api.pbobjc.m +++ b/objectivec/google/protobuf/Api.pbobjc.m @@ -7,6 +7,9 @@ #import "google/protobuf/Type.pbobjc.h" // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + #pragma mark - GPBApiRoot @implementation GPBApiRoot @@ -340,4 +343,6 @@ typedef struct GPBMixin__storage_ { @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 3685a614..29888d6c 100644 --- a/objectivec/google/protobuf/Duration.pbobjc.h +++ b/objectivec/google/protobuf/Duration.pbobjc.h @@ -9,6 +9,9 @@ // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + CF_EXTERN_C_BEGIN NS_ASSUME_NONNULL_BEGIN @@ -93,4 +96,6 @@ NS_ASSUME_NONNULL_END CF_EXTERN_C_END +#pragma clang diagnostic pop + // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Duration.pbobjc.m b/objectivec/google/protobuf/Duration.pbobjc.m index bb79c7a3..7dd6b64a 100644 --- a/objectivec/google/protobuf/Duration.pbobjc.m +++ b/objectivec/google/protobuf/Duration.pbobjc.m @@ -5,6 +5,9 @@ #import "google/protobuf/Duration.pbobjc.h" // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + #pragma mark - GPBDurationRoot @implementation GPBDurationRoot @@ -80,4 +83,6 @@ typedef struct GPBDuration__storage_ { @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 6651ef71..f33db017 100644 --- a/objectivec/google/protobuf/Empty.pbobjc.h +++ b/objectivec/google/protobuf/Empty.pbobjc.h @@ -9,6 +9,9 @@ // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + CF_EXTERN_C_BEGIN NS_ASSUME_NONNULL_BEGIN @@ -45,4 +48,6 @@ NS_ASSUME_NONNULL_END CF_EXTERN_C_END +#pragma clang diagnostic pop + // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Empty.pbobjc.m b/objectivec/google/protobuf/Empty.pbobjc.m index 5d7f8f19..88753aaf 100644 --- a/objectivec/google/protobuf/Empty.pbobjc.m +++ b/objectivec/google/protobuf/Empty.pbobjc.m @@ -5,6 +5,9 @@ #import "google/protobuf/Empty.pbobjc.h" // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + #pragma mark - GPBEmptyRoot @implementation GPBEmptyRoot @@ -56,4 +59,6 @@ typedef struct GPBEmpty__storage_ { @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 931f664c..73cbd8a5 100644 --- a/objectivec/google/protobuf/FieldMask.pbobjc.h +++ b/objectivec/google/protobuf/FieldMask.pbobjc.h @@ -9,6 +9,9 @@ // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + CF_EXTERN_C_BEGIN NS_ASSUME_NONNULL_BEGIN @@ -81,7 +84,7 @@ typedef GPB_ENUM(GPBFieldMask_FieldNumber) { /// operation applies to all fields (as if a FieldMask of all fields /// had been specified). /// -/// Note that a field mask does not necessarily applies to the +/// 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 @@ -154,6 +157,33 @@ typedef GPB_ENUM(GPBFieldMask_FieldNumber) { /// { /// 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. @@ -167,4 +197,6 @@ NS_ASSUME_NONNULL_END CF_EXTERN_C_END +#pragma clang diagnostic pop + // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.m b/objectivec/google/protobuf/FieldMask.pbobjc.m index 36fc758e..8c241afc 100644 --- a/objectivec/google/protobuf/FieldMask.pbobjc.m +++ b/objectivec/google/protobuf/FieldMask.pbobjc.m @@ -5,6 +5,9 @@ #import "google/protobuf/FieldMask.pbobjc.h" // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + #pragma mark - GPBFieldMaskRoot @implementation GPBFieldMaskRoot @@ -69,4 +72,6 @@ typedef struct GPBFieldMask__storage_ { @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 67b6d479..8775348e 100644 --- a/objectivec/google/protobuf/SourceContext.pbobjc.h +++ b/objectivec/google/protobuf/SourceContext.pbobjc.h @@ -9,6 +9,9 @@ // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + CF_EXTERN_C_BEGIN NS_ASSUME_NONNULL_BEGIN @@ -46,4 +49,6 @@ NS_ASSUME_NONNULL_END CF_EXTERN_C_END +#pragma clang diagnostic pop + // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.m b/objectivec/google/protobuf/SourceContext.pbobjc.m index 4e8bf3d2..95007126 100644 --- a/objectivec/google/protobuf/SourceContext.pbobjc.m +++ b/objectivec/google/protobuf/SourceContext.pbobjc.m @@ -5,6 +5,9 @@ #import "google/protobuf/SourceContext.pbobjc.h" // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + #pragma mark - GPBSourceContextRoot @implementation GPBSourceContextRoot @@ -69,4 +72,6 @@ typedef struct GPBSourceContext__storage_ { @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 e2388e22..3924b4b7 100644 --- a/objectivec/google/protobuf/Struct.pbobjc.h +++ b/objectivec/google/protobuf/Struct.pbobjc.h @@ -9,6 +9,9 @@ // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + CF_EXTERN_C_BEGIN @class GPBListValue; @@ -67,7 +70,7 @@ typedef GPB_ENUM(GPBStruct_FieldNumber) { /// The JSON representation for `Struct` is JSON object. @interface GPBStruct : GPBMessage -/// Map of dynamically typed values. +/// Unordered map of dynamically typed values. @property(nonatomic, readwrite, strong, null_resettable) NSMutableDictionary<NSString*, GPBValue*> *fields; /// The number of items in @c fields without causing the array to be created. @property(nonatomic, readonly) NSUInteger fields_Count; @@ -159,4 +162,6 @@ NS_ASSUME_NONNULL_END CF_EXTERN_C_END +#pragma clang diagnostic pop + // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Struct.pbobjc.m b/objectivec/google/protobuf/Struct.pbobjc.m index 0601a4b2..60940027 100644 --- a/objectivec/google/protobuf/Struct.pbobjc.m +++ b/objectivec/google/protobuf/Struct.pbobjc.m @@ -5,6 +5,9 @@ #import "google/protobuf/Struct.pbobjc.h" // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + #pragma mark - GPBStructRoot @implementation GPBStructRoot @@ -265,4 +268,6 @@ typedef struct GPBListValue__storage_ { @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 b66b323a..925dca84 100644 --- a/objectivec/google/protobuf/Timestamp.pbobjc.h +++ b/objectivec/google/protobuf/Timestamp.pbobjc.h @@ -9,6 +9,9 @@ // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + CF_EXTERN_C_BEGIN NS_ASSUME_NONNULL_BEGIN @@ -105,4 +108,6 @@ NS_ASSUME_NONNULL_END CF_EXTERN_C_END +#pragma clang diagnostic pop + // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.m b/objectivec/google/protobuf/Timestamp.pbobjc.m index 14161159..f35e435d 100644 --- a/objectivec/google/protobuf/Timestamp.pbobjc.m +++ b/objectivec/google/protobuf/Timestamp.pbobjc.m @@ -5,6 +5,9 @@ #import "google/protobuf/Timestamp.pbobjc.h" // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + #pragma mark - GPBTimestampRoot @implementation GPBTimestampRoot @@ -80,4 +83,6 @@ typedef struct GPBTimestamp__storage_ { @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 efaeab39..590d970b 100644 --- a/objectivec/google/protobuf/Type.pbobjc.h +++ b/objectivec/google/protobuf/Type.pbobjc.h @@ -9,6 +9,9 @@ // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + CF_EXTERN_C_BEGIN @class GPBAny; @@ -365,4 +368,6 @@ NS_ASSUME_NONNULL_END CF_EXTERN_C_END +#pragma clang diagnostic pop + // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Type.pbobjc.m b/objectivec/google/protobuf/Type.pbobjc.m index 175c0233..5554a222 100644 --- a/objectivec/google/protobuf/Type.pbobjc.m +++ b/objectivec/google/protobuf/Type.pbobjc.m @@ -7,6 +7,9 @@ #import "google/protobuf/SourceContext.pbobjc.h" // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + #pragma mark - GPBTypeRoot @implementation GPBTypeRoot @@ -685,4 +688,6 @@ typedef struct GPBOption__storage_ { @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 0ca439a8..46510500 100644 --- a/objectivec/google/protobuf/Wrappers.pbobjc.h +++ b/objectivec/google/protobuf/Wrappers.pbobjc.h @@ -9,6 +9,9 @@ // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + CF_EXTERN_C_BEGIN NS_ASSUME_NONNULL_BEGIN @@ -174,4 +177,6 @@ NS_ASSUME_NONNULL_END CF_EXTERN_C_END +#pragma clang diagnostic pop + // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.m b/objectivec/google/protobuf/Wrappers.pbobjc.m index b1b5be69..5cc6c2e4 100644 --- a/objectivec/google/protobuf/Wrappers.pbobjc.m +++ b/objectivec/google/protobuf/Wrappers.pbobjc.m @@ -5,6 +5,9 @@ #import "google/protobuf/Wrappers.pbobjc.h" // @@protoc_insertion_point(imports) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + #pragma mark - GPBWrappersRoot @implementation GPBWrappersRoot @@ -412,4 +415,6 @@ typedef struct GPBBytesValue__storage_ { @end +#pragma clang diagnostic pop + // @@protoc_insertion_point(global_scope) diff --git a/php/tests/autoload.php b/php/tests/autoload.php new file mode 100644 index 00000000..af88ba01 --- /dev/null +++ b/php/tests/autoload.php @@ -0,0 +1,4 @@ +<?php + +require_once('test.pb.php'); +require_once('test_util.php'); diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py index 5f613c88..3209b34d 100755 --- a/python/google/protobuf/descriptor.py +++ b/python/google/protobuf/descriptor.py @@ -783,6 +783,8 @@ class FileDescriptor(DescriptorBase): 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. @@ -794,7 +796,8 @@ class FileDescriptor(DescriptorBase): _C_DESCRIPTOR_CLASS = _message.FileDescriptor def __new__(cls, name, package, options=None, serialized_pb=None, - dependencies=None, syntax=None, pool=None): + dependencies=None, public_dependencies=None, + syntax=None, pool=None): # FileDescriptor() is called from various places, not only from generated # files, to register dynamic proto files and messages. if serialized_pb: @@ -805,7 +808,8 @@ class FileDescriptor(DescriptorBase): return super(FileDescriptor, cls).__new__(cls) def __init__(self, name, package, options=None, serialized_pb=None, - dependencies=None, syntax=None, pool=None): + dependencies=None, public_dependencies=None, + syntax=None, pool=None): """Constructor.""" super(FileDescriptor, self).__init__(options, 'FileOptions') @@ -822,6 +826,7 @@ class FileDescriptor(DescriptorBase): self.enum_types_by_name = {} self.extensions_by_name = {} self.dependencies = (dependencies or []) + self.public_dependencies = (public_dependencies or []) if (api_implementation.Type() == 'cpp' and self.serialized_pb is not None): diff --git a/python/google/protobuf/descriptor_pool.py b/python/google/protobuf/descriptor_pool.py index 3e80795c..20a33701 100644 --- a/python/google/protobuf/descriptor_pool.py +++ b/python/google/protobuf/descriptor_pool.py @@ -319,6 +319,7 @@ class DescriptorPool(object): 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] + public_deps = [direct_deps[i] for i in file_proto.public_dependency] file_descriptor = descriptor.FileDescriptor( pool=self, @@ -327,7 +328,8 @@ class DescriptorPool(object): syntax=file_proto.syntax, options=file_proto.options, serialized_pb=file_proto.SerializeToString(), - dependencies=direct_deps) + dependencies=direct_deps, + public_dependencies=public_deps) if _USE_C_DESCRIPTORS: # When using C++ descriptors, all objects defined in the file were added # to the C++ database when the FileDescriptor was built above. diff --git a/python/google/protobuf/internal/api_implementation.py b/python/google/protobuf/internal/api_implementation.py index ffcf7511..460a4a6c 100755 --- a/python/google/protobuf/internal/api_implementation.py +++ b/python/google/protobuf/internal/api_implementation.py @@ -32,6 +32,7 @@ """ import os +import warnings import sys try: @@ -78,6 +79,11 @@ _implementation_type = os.getenv('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION', if _implementation_type != 'python': _implementation_type = 'cpp' +if 'PyPy' in sys.version and _implementation_type == 'cpp': + warnings.warn('PyPy does not work yet with cpp protocol buffers. ' + 'Falling back to the python implementation.') + _implementation_type = 'python' + # This environment variable can be used to switch between the two # 'cpp' implementations, overriding the compile-time constants in the # _api_implementation module. Right now only '2' is supported. Any other diff --git a/python/google/protobuf/internal/descriptor_pool_test.py b/python/google/protobuf/internal/descriptor_pool_test.py index 4b1811d8..6a13e0bc 100644 --- a/python/google/protobuf/internal/descriptor_pool_test.py +++ b/python/google/protobuf/internal/descriptor_pool_test.py @@ -51,6 +51,7 @@ from google.protobuf.internal import descriptor_pool_test1_pb2 from google.protobuf.internal import descriptor_pool_test2_pb2 from google.protobuf.internal import factory_test1_pb2 from google.protobuf.internal import factory_test2_pb2 +from google.protobuf.internal import more_messages_pb2 from google.protobuf import descriptor from google.protobuf import descriptor_database from google.protobuf import descriptor_pool @@ -60,11 +61,8 @@ from google.protobuf import symbol_database class DescriptorPoolTest(unittest.TestCase): - def CreatePool(self): - return descriptor_pool.DescriptorPool() - def setUp(self): - self.pool = self.CreatePool() + self.pool = descriptor_pool.DescriptorPool() self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString( factory_test1_pb2.DESCRIPTOR.serialized_pb) self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString( @@ -275,10 +273,13 @@ class DescriptorPoolTest(unittest.TestCase): self.testFindMessageTypeByName() def testComplexNesting(self): + more_messages_desc = descriptor_pb2.FileDescriptorProto.FromString( + more_messages_pb2.DESCRIPTOR.serialized_pb) test1_desc = descriptor_pb2.FileDescriptorProto.FromString( descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb) test2_desc = descriptor_pb2.FileDescriptorProto.FromString( descriptor_pool_test2_pb2.DESCRIPTOR.serialized_pb) + self.pool.Add(more_messages_desc) self.pool.Add(test1_desc) self.pool.Add(test2_desc) TEST1_FILE.CheckFile(self, self.pool) @@ -350,25 +351,15 @@ class DescriptorPoolTest(unittest.TestCase): _CheckDefaultValues(message_class()) -@unittest.skipIf(api_implementation.Type() != 'cpp', - 'explicit tests of the C++ implementation') -class CppDescriptorPoolTest(DescriptorPoolTest): - # TODO(amauryfa): remove when descriptor_pool.DescriptorPool() creates true - # C++ descriptor pool object for C++ implementation. - - def CreatePool(self): - # pylint: disable=g-import-not-at-top - from google.protobuf.pyext import _message - return _message.DescriptorPool() - - class ProtoFile(object): - def __init__(self, name, package, messages, dependencies=None): + def __init__(self, name, package, messages, dependencies=None, + public_dependencies=None): self.name = name self.package = package self.messages = messages self.dependencies = dependencies or [] + self.public_dependencies = public_dependencies or [] def CheckFile(self, test, pool): file_desc = pool.FindFileByName(self.name) @@ -376,6 +367,8 @@ class ProtoFile(object): test.assertEqual(self.package, file_desc.package) dependencies_names = [f.name for f in file_desc.dependencies] test.assertEqual(self.dependencies, dependencies_names) + public_dependencies_names = [f.name for f in file_desc.public_dependencies] + test.assertEqual(self.public_dependencies, public_dependencies_names) for name, msg_type in self.messages.items(): msg_type.CheckType(test, None, name, file_desc) @@ -613,18 +606,9 @@ class AddDescriptorTest(unittest.TestCase): pool.FindFileContainingSymbol( 'protobuf_unittest.TestAllTypes') - def _GetDescriptorPoolClass(self): - # Test with both implementations of descriptor pools. - if api_implementation.Type() == 'cpp': - # pylint: disable=g-import-not-at-top - from google.protobuf.pyext import _message - return _message.DescriptorPool - else: - return descriptor_pool.DescriptorPool - def testEmptyDescriptorPool(self): - # Check that an empty DescriptorPool() contains no message. - pool = self._GetDescriptorPoolClass()() + # Check that an empty DescriptorPool() contains no messages. + pool = descriptor_pool.DescriptorPool() proto_file_name = descriptor_pb2.DESCRIPTOR.name self.assertRaises(KeyError, pool.FindFileByName, proto_file_name) # Add the above file to the pool @@ -636,7 +620,7 @@ class AddDescriptorTest(unittest.TestCase): def testCustomDescriptorPool(self): # Create a new pool, and add a file descriptor. - pool = self._GetDescriptorPoolClass()() + pool = descriptor_pool.DescriptorPool() file_desc = descriptor_pb2.FileDescriptorProto( name='some/file.proto', package='package') file_desc.message_type.add(name='Message') @@ -757,7 +741,9 @@ TEST2_FILE = ProtoFile( ExtensionField(1001, 'DescriptorPoolTest1')), ]), }, - dependencies=['google/protobuf/internal/descriptor_pool_test1.proto']) + dependencies=['google/protobuf/internal/descriptor_pool_test1.proto', + 'google/protobuf/internal/more_messages.proto'], + public_dependencies=['google/protobuf/internal/more_messages.proto']) if __name__ == '__main__': diff --git a/python/google/protobuf/internal/descriptor_pool_test2.proto b/python/google/protobuf/internal/descriptor_pool_test2.proto index e3fa660c..a218eccb 100644 --- a/python/google/protobuf/internal/descriptor_pool_test2.proto +++ b/python/google/protobuf/internal/descriptor_pool_test2.proto @@ -33,6 +33,7 @@ syntax = "proto2"; package google.protobuf.python.internal; import "google/protobuf/internal/descriptor_pool_test1.proto"; +import public "google/protobuf/internal/more_messages.proto"; message DescriptorPoolTest3 { diff --git a/python/google/protobuf/internal/message_factory_test.py b/python/google/protobuf/internal/message_factory_test.py index 54b1f688..7bb7d1ac 100644 --- a/python/google/protobuf/internal/message_factory_test.py +++ b/python/google/protobuf/internal/message_factory_test.py @@ -131,6 +131,60 @@ class MessageFactoryTest(unittest.TestCase): self.assertEqual('test1', msg1.Extensions[ext1]) self.assertEqual('test2', msg1.Extensions[ext2]) + def testDuplicateExtensionNumber(self): + pool = descriptor_pool.DescriptorPool() + factory = message_factory.MessageFactory(pool=pool) + + # Add Container message. + f = descriptor_pb2.FileDescriptorProto() + f.name = 'google/protobuf/internal/container.proto' + f.package = 'google.protobuf.python.internal' + msg = f.message_type.add() + msg.name = 'Container' + rng = msg.extension_range.add() + rng.start = 1 + rng.end = 10 + pool.Add(f) + msgs = factory.GetMessages([f.name]) + self.assertIn('google.protobuf.python.internal.Container', msgs) + + # Extend container. + f = descriptor_pb2.FileDescriptorProto() + f.name = 'google/protobuf/internal/extension.proto' + f.package = 'google.protobuf.python.internal' + f.dependency.append('google/protobuf/internal/container.proto') + msg = f.message_type.add() + msg.name = 'Extension' + ext = msg.extension.add() + ext.name = 'extension_field' + ext.number = 2 + ext.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL + ext.type_name = 'Extension' + ext.extendee = 'Container' + pool.Add(f) + msgs = factory.GetMessages([f.name]) + self.assertIn('google.protobuf.python.internal.Extension', msgs) + + # Add Duplicate extending the same field number. + f = descriptor_pb2.FileDescriptorProto() + f.name = 'google/protobuf/internal/duplicate.proto' + f.package = 'google.protobuf.python.internal' + f.dependency.append('google/protobuf/internal/container.proto') + msg = f.message_type.add() + msg.name = 'Duplicate' + ext = msg.extension.add() + ext.name = 'extension_field' + ext.number = 2 + ext.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL + ext.type_name = 'Duplicate' + ext.extendee = 'Container' + pool.Add(f) + + with self.assertRaises(Exception) as cm: + factory.GetMessages([f.name]) + + self.assertIsInstance(cm.exception, (AssertionError, ValueError)) + if __name__ == '__main__': unittest.main() diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py index 1232ccc9..4ee31d8e 100755 --- a/python/google/protobuf/internal/message_test.py +++ b/python/google/protobuf/internal/message_test.py @@ -57,18 +57,18 @@ try: except ImportError: import unittest -from google.protobuf.internal import _parameterized +from google.protobuf import map_unittest_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_pool -from google.protobuf import map_unittest_pb2 from google.protobuf import message_factory from google.protobuf import text_format -from google.protobuf import unittest_pb2 -from google.protobuf import unittest_proto3_arena_pb2 from google.protobuf.internal import api_implementation from google.protobuf.internal import packed_field_test_pb2 from google.protobuf.internal import test_util from google.protobuf import message +from google.protobuf.internal import _parameterized if six.PY3: long = int @@ -1265,7 +1265,10 @@ class Proto3Test(unittest.TestCase): self.assertFalse(-2**33 in msg.map_int64_int64) self.assertFalse(123 in msg.map_uint32_uint32) self.assertFalse(2**33 in msg.map_uint64_uint64) + self.assertFalse(123 in msg.map_int32_double) + self.assertFalse(False in msg.map_bool_bool) self.assertFalse('abc' in msg.map_string_string) + self.assertFalse(111 in msg.map_int32_bytes) self.assertFalse(888 in msg.map_int32_enum) # Accessing an unset key returns the default. @@ -1273,7 +1276,12 @@ class Proto3Test(unittest.TestCase): self.assertEqual(0, msg.map_int64_int64[-2**33]) self.assertEqual(0, msg.map_uint32_uint32[123]) self.assertEqual(0, msg.map_uint64_uint64[2**33]) + self.assertEqual(0.0, msg.map_int32_double[123]) + self.assertTrue(isinstance(msg.map_int32_double[123], float)) + self.assertEqual(False, msg.map_bool_bool[False]) + self.assertTrue(isinstance(msg.map_bool_bool[False], bool)) self.assertEqual('', msg.map_string_string['abc']) + self.assertEqual(b'', msg.map_int32_bytes[111]) self.assertEqual(0, msg.map_int32_enum[888]) # It also sets the value in the map @@ -1281,7 +1289,10 @@ class Proto3Test(unittest.TestCase): self.assertTrue(-2**33 in msg.map_int64_int64) self.assertTrue(123 in msg.map_uint32_uint32) self.assertTrue(2**33 in msg.map_uint64_uint64) + self.assertTrue(123 in msg.map_int32_double) + self.assertTrue(False in msg.map_bool_bool) self.assertTrue('abc' in msg.map_string_string) + self.assertTrue(111 in msg.map_int32_bytes) self.assertTrue(888 in msg.map_int32_enum) self.assertIsInstance(msg.map_string_string['abc'], six.text_type) @@ -1587,6 +1598,21 @@ class Proto3Test(unittest.TestCase): matching_dict = {2: 4, 3: 6, 4: 8} self.assertMapIterEquals(msg.map_int32_int32.items(), matching_dict) + def testMapItems(self): + # Map items used to have strange behaviors when use c extension. Because + # [] may reorder the map and invalidate any exsting iterators. + # TODO(jieluo): Check if [] reordering the map is a bug or intended + # behavior. + msg = map_unittest_pb2.TestMap() + msg.map_string_string['local_init_op'] = '' + msg.map_string_string['trainable_variables'] = '' + msg.map_string_string['variables'] = '' + msg.map_string_string['init_op'] = '' + msg.map_string_string['summaries'] = '' + items1 = msg.map_string_string.items() + items2 = msg.map_string_string.items() + self.assertEqual(items1, items2) + def testMapIterationClearMessage(self): # Iterator needs to work even if message and map are deleted. msg = map_unittest_pb2.TestMap() diff --git a/python/google/protobuf/internal/proto_builder_test.py b/python/google/protobuf/internal/proto_builder_test.py index 822ad895..36dfbfde 100644 --- a/python/google/protobuf/internal/proto_builder_test.py +++ b/python/google/protobuf/internal/proto_builder_test.py @@ -40,6 +40,7 @@ try: import unittest2 as unittest except ImportError: import unittest + from google.protobuf import descriptor_pb2 from google.protobuf import descriptor_pool from google.protobuf import proto_builder diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py index 87f60666..f8f73dd2 100755 --- a/python/google/protobuf/internal/python_message.py +++ b/python/google/protobuf/internal/python_message.py @@ -56,7 +56,14 @@ import struct import weakref import six -import six.moves.copyreg as copyreg +try: + import six.moves.copyreg as copyreg +except ImportError: + # On some platforms, for example gMac, we run native Python because there is + # nothing like hermetic Python. This means lesser control on the system and + # the six.moves package may be missing (is missing on 20150321 on gMac). Be + # extra conservative and try to load the old replacement if it fails. + import copy_reg as copyreg # We use "as" to avoid name collisions with variables. from google.protobuf.internal import containers @@ -490,6 +497,9 @@ def _AddInitMethod(message_descriptor, cls): if field is None: 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. + continue if field.label == _FieldDescriptor.LABEL_REPEATED: copy = field._default_constructor(self) if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: # Composite @@ -889,17 +899,6 @@ def _AddClearExtensionMethod(cls): cls.ClearExtension = ClearExtension -def _AddClearMethod(message_descriptor, cls): - """Helper for _AddMessageMethods().""" - def Clear(self): - # Clear fields. - self._fields = {} - self._unknown_fields = () - self._oneofs = {} - self._Modified() - cls.Clear = Clear - - def _AddHasExtensionMethod(cls): """Helper for _AddMessageMethods().""" def HasExtension(self, extension_handle): @@ -999,16 +998,6 @@ def _AddUnicodeMethod(unused_message_descriptor, cls): cls.__unicode__ = __unicode__ -def _AddSetListenerMethod(cls): - """Helper for _AddMessageMethods().""" - def SetListener(self, listener): - if listener is None: - self._listener = message_listener_mod.NullMessageListener() - else: - self._listener = listener - cls._SetListener = SetListener - - def _BytesForNonRepeatedElement(value, field_number, field_type): """Returns the number of bytes needed to serialize a non-repeated element. The returned byte count includes space for tag information and any @@ -1288,6 +1277,32 @@ def _AddWhichOneofMethod(message_descriptor, cls): cls.WhichOneof = WhichOneof +def _Clear(self): + # Clear fields. + self._fields = {} + self._unknown_fields = () + self._oneofs = {} + self._Modified() + + +def _DiscardUnknownFields(self): + self._unknown_fields = [] + for field, value in self.ListFields(): + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + if field.label == _FieldDescriptor.LABEL_REPEATED: + for sub_message in value: + sub_message.DiscardUnknownFields() + else: + value.DiscardUnknownFields() + + +def _SetListener(self, listener): + if listener is None: + self._listener = message_listener_mod.NullMessageListener() + else: + self._listener = listener + + def _AddMessageMethods(message_descriptor, cls): """Adds implementations of all Message methods to cls.""" _AddListFieldsMethod(message_descriptor, cls) @@ -1296,12 +1311,10 @@ def _AddMessageMethods(message_descriptor, cls): if message_descriptor.is_extendable: _AddClearExtensionMethod(cls) _AddHasExtensionMethod(cls) - _AddClearMethod(message_descriptor, cls) _AddEqualsMethod(message_descriptor, cls) _AddStrMethod(message_descriptor, cls) _AddReprMethod(message_descriptor, cls) _AddUnicodeMethod(message_descriptor, cls) - _AddSetListenerMethod(cls) _AddByteSizeMethod(message_descriptor, cls) _AddSerializeToStringMethod(message_descriptor, cls) _AddSerializePartialToStringMethod(message_descriptor, cls) @@ -1309,6 +1322,10 @@ def _AddMessageMethods(message_descriptor, cls): _AddIsInitializedMethod(message_descriptor, cls) _AddMergeFromMethod(cls) _AddWhichOneofMethod(message_descriptor, cls) + # Adds methods which do not depend on cls. + cls.Clear = _Clear + cls.DiscardUnknownFields = _DiscardUnknownFields + cls._SetListener = _SetListener def _AddPrivateHelperMethods(message_descriptor, cls): @@ -1518,3 +1535,14 @@ class _ExtensionDict(object): 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/reflection_test.py b/python/google/protobuf/internal/reflection_test.py index 9e61ea0e..6dc2fffe 100755 --- a/python/google/protobuf/internal/reflection_test.py +++ b/python/google/protobuf/internal/reflection_test.py @@ -120,11 +120,13 @@ class ReflectionTest(unittest.TestCase): proto = unittest_pb2.TestAllTypes( optional_int32=24, optional_double=54.321, - optional_string='optional_string') + optional_string='optional_string', + optional_float=None) 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")) def testRepeatedScalarConstructor(self): # Constructor with only repeated scalar types should succeed. @@ -132,12 +134,14 @@ class ReflectionTest(unittest.TestCase): repeated_int32=[1, 2, 3, 4], repeated_double=[1.23, 54.321], repeated_bool=[True, False, False], - repeated_string=["optional_string"]) + repeated_string=["optional_string"], + repeated_float=None) self.assertEqual([1, 2, 3, 4], list(proto.repeated_int32)) self.assertEqual([1.23, 54.321], list(proto.repeated_double)) self.assertEqual([True, False, False], list(proto.repeated_bool)) 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. @@ -188,7 +192,8 @@ class ReflectionTest(unittest.TestCase): repeated_foreign_message=[ unittest_pb2.ForeignMessage(c=-43), unittest_pb2.ForeignMessage(c=45324), - unittest_pb2.ForeignMessage(c=12)]) + unittest_pb2.ForeignMessage(c=12)], + optional_nested_message=None) self.assertEqual(24, proto.optional_int32) self.assertEqual('optional_string', proto.optional_string) @@ -205,6 +210,7 @@ class ReflectionTest(unittest.TestCase): unittest_pb2.ForeignMessage(c=45324), unittest_pb2.ForeignMessage(c=12)], list(proto.repeated_foreign_message)) + self.assertFalse(proto.HasField("optional_nested_message")) def testConstructorTypeError(self): self.assertRaises( diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py index 8ce0a44f..ab2bf05b 100755 --- a/python/google/protobuf/internal/text_format_test.py +++ b/python/google/protobuf/internal/text_format_test.py @@ -250,6 +250,36 @@ class TextFormatTest(TextFormatBase): message.c = 123 self.assertEqual('c: 123\n', str(message)) + def testPrintField(self, message_module): + message = message_module.TestAllTypes() + field = message.DESCRIPTOR.fields_by_name['optional_float'] + value = message.optional_float + out = text_format.TextWriter(False) + text_format.PrintField(field, value, out) + self.assertEqual('optional_float: 0.0\n', out.getvalue()) + out.close() + # Test Printer + out = text_format.TextWriter(False) + printer = text_format._Printer(out) + printer.PrintField(field, value) + self.assertEqual('optional_float: 0.0\n', out.getvalue()) + out.close() + + def testPrintFieldValue(self, message_module): + message = message_module.TestAllTypes() + field = message.DESCRIPTOR.fields_by_name['optional_float'] + value = message.optional_float + out = text_format.TextWriter(False) + text_format.PrintFieldValue(field, value, out) + self.assertEqual('0.0', out.getvalue()) + out.close() + # Test Printer + out = text_format.TextWriter(False) + printer = text_format._Printer(out) + printer.PrintFieldValue(field, value) + self.assertEqual('0.0', out.getvalue()) + out.close() + def testParseAllFields(self, message_module): message = message_module.TestAllTypes() test_util.SetAllFields(message) @@ -616,6 +646,26 @@ class Proto2Tests(TextFormatBase): ' text: \"bar\"\n' '}\n') + def testPrintMessageSetByFieldNumber(self): + out = text_format.TextWriter(False) + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + text_format.PrintMessage(message, out, use_field_number=True) + self.CompareToGoldenText( + out.getvalue(), + '1 {\n' + ' 1545008 {\n' + ' 15: 23\n' + ' }\n' + ' 1547769 {\n' + ' 25: \"foo\"\n' + ' }\n' + '}\n') + out.close() + def testPrintMessageSetAsOneLine(self): message = unittest_mset_pb2.TestMessageSetContainer() ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension @@ -656,6 +706,48 @@ class Proto2Tests(TextFormatBase): self.assertEqual(23, message.message_set.Extensions[ext1].i) self.assertEqual('foo', message.message_set.Extensions[ext2].str) + def testParseMessageByFieldNumber(self): + message = unittest_pb2.TestAllTypes() + text = ('34: 1\n' + 'repeated_uint64: 2\n') + text_format.Parse(text, message, allow_field_number=True) + self.assertEqual(1, message.repeated_uint64[0]) + self.assertEqual(2, message.repeated_uint64[1]) + + message = unittest_mset_pb2.TestMessageSetContainer() + text = ('1 {\n' + ' 1545008 {\n' + ' 15: 23\n' + ' }\n' + ' 1547769 {\n' + ' 25: \"foo\"\n' + ' }\n' + '}\n') + text_format.Parse(text, message, allow_field_number=True) + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + self.assertEqual(23, message.message_set.Extensions[ext1].i) + self.assertEqual('foo', message.message_set.Extensions[ext2].str) + + # Can't parse field number without set allow_field_number=True. + message = unittest_pb2.TestAllTypes() + text = '34:1\n' + six.assertRaisesRegex( + self, + text_format.ParseError, + (r'1:1 : Message type "\w+.TestAllTypes" has no field named ' + r'"34".'), + text_format.Parse, text, message) + + # Can't parse if field number is not found. + text = '1234:1\n' + six.assertRaisesRegex( + self, + text_format.ParseError, + (r'1:1 : Message type "\w+.TestAllTypes" has no field named ' + r'"1234".'), + text_format.Parse, text, message, allow_field_number=True) + def testPrintAllExtensions(self): message = unittest_pb2.TestAllExtensions() test_util.SetAllExtensions(message) @@ -696,6 +788,7 @@ class Proto2Tests(TextFormatBase): text = ('message_set {\n' ' [unknown_extension] {\n' ' i: 23\n' + ' bin: "\xe0"' ' [nested_unknown_ext]: {\n' ' i: 23\n' ' test: "test_string"\n' diff --git a/python/google/protobuf/internal/type_checkers.py b/python/google/protobuf/internal/type_checkers.py index f30ca6a8..1be3ad9a 100755 --- a/python/google/protobuf/internal/type_checkers.py +++ b/python/google/protobuf/internal/type_checkers.py @@ -109,6 +109,16 @@ class TypeChecker(object): return proposed_value +class TypeCheckerWithDefault(TypeChecker): + + def __init__(self, default_value, *acceptable_types): + TypeChecker.__init__(self, acceptable_types) + self._default_value = default_value + + def DefaultValue(self): + return self._default_value + + # IntValueChecker and its subclasses perform integer type-checks # and bounds-checks. class IntValueChecker(object): @@ -212,12 +222,13 @@ _VALUE_CHECKERS = { _FieldDescriptor.CPPTYPE_INT64: Int64ValueChecker(), _FieldDescriptor.CPPTYPE_UINT32: Uint32ValueChecker(), _FieldDescriptor.CPPTYPE_UINT64: Uint64ValueChecker(), - _FieldDescriptor.CPPTYPE_DOUBLE: TypeChecker( - float, int, long), - _FieldDescriptor.CPPTYPE_FLOAT: TypeChecker( - float, int, long), - _FieldDescriptor.CPPTYPE_BOOL: TypeChecker(bool, int), - _FieldDescriptor.CPPTYPE_STRING: TypeChecker(bytes), + _FieldDescriptor.CPPTYPE_DOUBLE: TypeCheckerWithDefault( + 0.0, float, int, long), + _FieldDescriptor.CPPTYPE_FLOAT: TypeCheckerWithDefault( + 0.0, float, int, long), + _FieldDescriptor.CPPTYPE_BOOL: TypeCheckerWithDefault( + False, bool, int), + _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 bb2748e4..84073f1c 100755 --- a/python/google/protobuf/internal/unknown_fields_test.py +++ b/python/google/protobuf/internal/unknown_fields_test.py @@ -119,6 +119,26 @@ class UnknownFieldsTest(unittest.TestCase): message.ParseFromString(self.all_fields.SerializeToString()) self.assertNotEqual(self.empty_message, message) + def testDiscardUnknownFields(self): + self.empty_message.DiscardUnknownFields() + self.assertEqual(b'', self.empty_message.SerializeToString()) + # Test message field and repeated message field. + message = unittest_pb2.TestAllTypes() + other_message = unittest_pb2.TestAllTypes() + other_message.optional_string = 'discard' + message.optional_nested_message.ParseFromString( + other_message.SerializeToString()) + message.repeated_nested_message.add().ParseFromString( + other_message.SerializeToString()) + self.assertNotEqual( + b'', message.optional_nested_message.SerializeToString()) + self.assertNotEqual( + b'', message.repeated_nested_message[0].SerializeToString()) + message.DiscardUnknownFields() + self.assertEqual(b'', message.optional_nested_message.SerializeToString()) + self.assertEqual( + b'', message.repeated_nested_message[0].SerializeToString()) + class UnknownFieldsAccessorsTest(unittest.TestCase): diff --git a/python/google/protobuf/internal/well_known_types.py b/python/google/protobuf/internal/well_known_types.py index d35fcc5f..7c5dffd0 100644 --- a/python/google/protobuf/internal/well_known_types.py +++ b/python/google/protobuf/internal/well_known_types.py @@ -82,10 +82,14 @@ class Any(object): msg.ParseFromString(self.value) return True + def TypeName(self): + """Returns the protobuf type name of the inner message.""" + # Only last part is to be used: b/25630112 + return self.type_url.split('/')[-1] + def Is(self, descriptor): """Checks if this Any represents the given protobuf type.""" - # Only last part is to be used: b/25630112 - return self.type_url.split('/')[-1] == descriptor.full_name + return self.TypeName() == descriptor.full_name class Timestamp(object): diff --git a/python/google/protobuf/internal/well_known_types_test.py b/python/google/protobuf/internal/well_known_types_test.py index 18329205..2f32ac99 100644 --- a/python/google/protobuf/internal/well_known_types_test.py +++ b/python/google/protobuf/internal/well_known_types_test.py @@ -610,6 +610,14 @@ class AnyTest(unittest.TestCase): raise AttributeError('%s should not have Pack method.' % msg_descriptor.full_name) + def testMessageName(self): + # Creates and sets message. + submessage = any_test_pb2.TestAny() + submessage.int_value = 12345 + msg = any_pb2.Any() + msg.Pack(submessage) + self.assertEqual(msg.TypeName(), 'google.protobuf.internal.TestAny') + def testPackWithCustomTypeUrl(self): submessage = any_test_pb2.TestAny() submessage.int_value = 12345 diff --git a/python/google/protobuf/message.py b/python/google/protobuf/message.py index de2f5697..606f735f 100755 --- a/python/google/protobuf/message.py +++ b/python/google/protobuf/message.py @@ -255,6 +255,9 @@ class Message(object): def ClearExtension(self, extension_handle): raise NotImplementedError + def DiscardUnknownFields(self): + raise NotImplementedError + def ByteSize(self): """Returns the serialized size of this message. Recursively calls ByteSize() on all contained messages. diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc index 07550706..23557538 100644 --- a/python/google/protobuf/pyext/descriptor.cc +++ b/python/google/protobuf/pyext/descriptor.cc @@ -200,8 +200,8 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) { // read-only instance. const Message& options(descriptor->options()); const Descriptor *message_type = options.GetDescriptor(); - PyObject* message_class(cdescriptor_pool::GetMessageClass( - pool, message_type)); + CMessageClass* message_class( + cdescriptor_pool::GetMessageClass(pool, message_type)); if (message_class == NULL) { // The Options message was not found in the current DescriptorPool. // In this case, there cannot be extensions to these options, and we can @@ -215,7 +215,8 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) { message_type->full_name().c_str()); return NULL; } - ScopedPyObjectPtr value(PyEval_CallObject(message_class, NULL)); + ScopedPyObjectPtr value( + PyEval_CallObject(message_class->AsPyObject(), NULL)); if (value == NULL) { return NULL; } @@ -433,11 +434,11 @@ static PyObject* GetConcreteClass(PyBaseDescriptor* self, void *closure) { // which contains this descriptor. // This might not be the one you expect! For example the returned object does // not know about extensions defined in a custom pool. - PyObject* concrete_class(cdescriptor_pool::GetMessageClass( + CMessageClass* concrete_class(cdescriptor_pool::GetMessageClass( GetDescriptorPool_FromPool(_GetDescriptor(self)->file()->pool()), _GetDescriptor(self))); Py_XINCREF(concrete_class); - return concrete_class; + return concrete_class->AsPyObject(); } static PyObject* GetFieldsByName(PyBaseDescriptor* self, void *closure) { diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc index 0bc76bc9..1faff96b 100644 --- a/python/google/protobuf/pyext/descriptor_pool.cc +++ b/python/google/protobuf/pyext/descriptor_pool.cc @@ -190,8 +190,8 @@ PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) { // Add a message class to our database. int RegisterMessageClass(PyDescriptorPool* self, - const Descriptor *message_descriptor, - PyObject *message_class) { + const Descriptor* message_descriptor, + CMessageClass* message_class) { Py_INCREF(message_class); typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator; std::pair<iterator, bool> ret = self->classes_by_descriptor->insert( @@ -205,8 +205,8 @@ int RegisterMessageClass(PyDescriptorPool* self, } // Retrieve the message class added to our database. -PyObject *GetMessageClass(PyDescriptorPool* self, - const Descriptor *message_descriptor) { +CMessageClass* GetMessageClass(PyDescriptorPool* self, + const Descriptor* message_descriptor) { typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator; iterator ret = self->classes_by_descriptor->find(message_descriptor); if (ret == self->classes_by_descriptor->end()) { diff --git a/python/google/protobuf/pyext/descriptor_pool.h b/python/google/protobuf/pyext/descriptor_pool.h index 16bc910c..2a42c112 100644 --- a/python/google/protobuf/pyext/descriptor_pool.h +++ b/python/google/protobuf/pyext/descriptor_pool.h @@ -42,6 +42,9 @@ class MessageFactory; namespace python { +// The (meta) type of all Messages classes. +struct CMessageClass; + // Wraps operations to the global DescriptorPool which contains information // about all messages and fields. // @@ -78,7 +81,7 @@ typedef struct PyDescriptorPool { // // Descriptor pointers stored here are owned by the DescriptorPool above. // Python references to classes are owned by this PyDescriptorPool. - typedef hash_map<const Descriptor*, PyObject*> ClassesByMessageMap; + typedef hash_map<const Descriptor*, CMessageClass*> ClassesByMessageMap; ClassesByMessageMap* classes_by_descriptor; // Cache the options for any kind of descriptor. @@ -101,14 +104,14 @@ const Descriptor* FindMessageTypeByName(PyDescriptorPool* self, // On error, returns -1 with a Python exception set. int RegisterMessageClass(PyDescriptorPool* self, const Descriptor* message_descriptor, - PyObject* message_class); + CMessageClass* message_class); // Retrieves the Python class registered with the given message descriptor. // // Returns a *borrowed* reference if found, otherwise returns NULL with an // exception set. -PyObject* GetMessageClass(PyDescriptorPool* self, - const Descriptor* message_descriptor); +CMessageClass* GetMessageClass(PyDescriptorPool* self, + const Descriptor* message_descriptor); // The functions below are also exposed as methods of the DescriptorPool type. diff --git a/python/google/protobuf/pyext/extension_dict.cc b/python/google/protobuf/pyext/extension_dict.cc index 555bd293..21bbb8c2 100644 --- a/python/google/protobuf/pyext/extension_dict.cc +++ b/python/google/protobuf/pyext/extension_dict.cc @@ -130,7 +130,7 @@ PyObject* subscript(ExtensionDict* self, PyObject* key) { if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - PyObject *message_class = cdescriptor_pool::GetMessageClass( + CMessageClass* message_class = cdescriptor_pool::GetMessageClass( cmessage::GetDescriptorPoolForMessage(self->parent), descriptor->message_type()); if (message_class == NULL) { @@ -239,6 +239,21 @@ PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* name) { } } +PyObject* _FindExtensionByNumber(ExtensionDict* self, PyObject* number) { + ScopedPyObjectPtr extensions_by_number(PyObject_GetAttrString( + reinterpret_cast<PyObject*>(self->parent), "_extensions_by_number")); + if (extensions_by_number == NULL) { + return NULL; + } + PyObject* result = PyDict_GetItem(extensions_by_number.get(), number); + if (result == NULL) { + Py_RETURN_NONE; + } else { + Py_INCREF(result); + return result; + } +} + ExtensionDict* NewExtensionDict(CMessage *parent) { ExtensionDict* self = reinterpret_cast<ExtensionDict*>( PyType_GenericAlloc(&ExtensionDict_Type, 0)); @@ -271,6 +286,8 @@ static PyMethodDef Methods[] = { EDMETHOD(HasExtension, METH_O, "Checks if the object has an extension."), EDMETHOD(_FindExtensionByName, METH_O, "Finds an extension by name."), + EDMETHOD(_FindExtensionByNumber, METH_O, + "Finds an extension by field number."), { NULL, NULL } }; diff --git a/python/google/protobuf/pyext/extension_dict.h b/python/google/protobuf/pyext/extension_dict.h index 1e7f6f7b..049d2e45 100644 --- a/python/google/protobuf/pyext/extension_dict.h +++ b/python/google/protobuf/pyext/extension_dict.h @@ -123,6 +123,12 @@ PyObject* ClearExtension(ExtensionDict* self, // Returns a new reference. PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* name); +// Gets an extension from the dict given the extension field number as +// opposed to descriptor. +// +// Returns a new reference. +PyObject* _FindExtensionByNumber(ExtensionDict* self, PyObject* number); + } // namespace extension_dict } // namespace python } // namespace protobuf diff --git a/python/google/protobuf/pyext/map_container.cc b/python/google/protobuf/pyext/map_container.cc index df9138a4..e022406d 100644 --- a/python/google/protobuf/pyext/map_container.cc +++ b/python/google/protobuf/pyext/map_container.cc @@ -32,6 +32,11 @@ #include <google/protobuf/pyext/map_container.h> +#include <memory> +#ifndef _SHARED_PTR_H +#include <google/protobuf/stubs/shared_ptr.h> +#endif + #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/scoped_ptr.h> @@ -70,7 +75,7 @@ class MapReflectionFriend { struct MapIterator { PyObject_HEAD; - scoped_ptr< ::google::protobuf::MapIterator> iter; + google::protobuf::scoped_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. @@ -610,8 +615,7 @@ static PyObject* GetCMessage(MessageMapContainer* self, Message* message) { PyObject* ret = PyDict_GetItem(self->message_dict, key.get()); if (ret == NULL) { - CMessage* cmsg = cmessage::NewEmptyMessage(self->subclass_init, - message->GetDescriptor()); + CMessage* cmsg = cmessage::NewEmptyMessage(self->message_class); ret = reinterpret_cast<PyObject*>(cmsg); if (cmsg == NULL) { @@ -634,7 +638,7 @@ static PyObject* GetCMessage(MessageMapContainer* self, Message* message) { PyObject* NewMessageMapContainer( CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor, - PyObject* concrete_class) { + CMessageClass* message_class) { if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) { return NULL; } @@ -669,8 +673,8 @@ PyObject* NewMessageMapContainer( "Could not allocate message dict."); } - Py_INCREF(concrete_class); - self->subclass_init = concrete_class; + Py_INCREF(message_class); + self->message_class = message_class; if (self->key_field_descriptor == NULL || self->value_field_descriptor == NULL) { @@ -763,6 +767,7 @@ static void MessageMapDealloc(PyObject* _self) { MessageMapContainer* self = GetMessageMap(_self); self->owner.reset(); Py_DECREF(self->message_dict); + Py_DECREF(self->message_class); Py_TYPE(_self)->tp_free(_self); } diff --git a/python/google/protobuf/pyext/map_container.h b/python/google/protobuf/pyext/map_container.h index 27ee6dbd..b11dfa34 100644 --- a/python/google/protobuf/pyext/map_container.h +++ b/python/google/protobuf/pyext/map_container.h @@ -55,6 +55,7 @@ using internal::shared_ptr; 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. @@ -104,8 +105,8 @@ struct MapContainer { }; struct MessageMapContainer : public MapContainer { - // A callable that is used to create new child messages. - PyObject* subclass_init; + // The type used to create new child messages. + CMessageClass* message_class; // A dict mapping Message* -> CMessage. PyObject* message_dict; @@ -132,7 +133,7 @@ extern PyObject* NewScalarMapContainer( // field descriptor. extern PyObject* NewMessageMapContainer( CMessage* parent, const FieldDescriptor* parent_field_descriptor, - PyObject* concrete_class); + CMessageClass* message_class); } // namespace python } // namespace protobuf diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc index 6d7b2b0f..83c151ff 100644 --- a/python/google/protobuf/pyext/message.cc +++ b/python/google/protobuf/pyext/message.cc @@ -98,31 +98,6 @@ static PyObject* PythonMessage_class; static PyObject* kEmptyWeakref; static PyObject* WKT_classes = NULL; -// Defines the Metaclass of all Message classes. -// It allows us to cache some C++ pointers in the class object itself, they are -// faster to extract than from the type's dictionary. - -struct PyMessageMeta { - // This is how CPython subclasses C structures: the base structure must be - // the first member of the object. - PyHeapTypeObject super; - - // C++ descriptor of this message. - const Descriptor* message_descriptor; - - // Owned reference, used to keep the pointer above alive. - PyObject* py_message_descriptor; - - // The Python DescriptorPool used to create the class. It is needed to resolve - // fields descriptors, including extensions fields; its C++ MessageFactory is - // used to instantiate submessages. - // This can be different from DESCRIPTOR.file.pool, in the case of a custom - // DescriptorPool which defines new extensions. - // We own the reference, because it's important to keep the descriptors and - // factory alive. - PyDescriptorPool* py_descriptor_pool; -}; - namespace message_meta { static int InsertEmptyWeakref(PyTypeObject* base); @@ -173,10 +148,6 @@ static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) { } // For each enum set cls.<enum name> = EnumTypeWrapper(<enum descriptor>). - // - // The enum descriptor we get from - // <messagedescriptor>.enum_types_by_name[name] - // which was built previously. for (int i = 0; i < descriptor->enum_type_count(); ++i) { const EnumDescriptor* enum_descriptor = descriptor->enum_type(i); ScopedPyObjectPtr enum_type( @@ -309,7 +280,7 @@ static PyObject* New(PyTypeObject* type, if (result == NULL) { return NULL; } - PyMessageMeta* newtype = reinterpret_cast<PyMessageMeta*>(result.get()); + CMessageClass* newtype = reinterpret_cast<CMessageClass*>(result.get()); // Insert the empty weakref into the base classes. if (InsertEmptyWeakref( @@ -338,7 +309,7 @@ static PyObject* New(PyTypeObject* type, // Add the message to the DescriptorPool. if (cdescriptor_pool::RegisterMessageClass(newtype->py_descriptor_pool, - descriptor, result.get()) < 0) { + descriptor, newtype) < 0) { return NULL; } @@ -349,7 +320,7 @@ static PyObject* New(PyTypeObject* type, return result.release(); } -static void Dealloc(PyMessageMeta *self) { +static void Dealloc(CMessageClass *self) { Py_DECREF(self->py_message_descriptor); Py_DECREF(self->py_descriptor_pool); Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); @@ -378,10 +349,10 @@ static int InsertEmptyWeakref(PyTypeObject *base_type) { } // namespace message_meta -PyTypeObject PyMessageMeta_Type = { +PyTypeObject CMessageClass_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME ".MessageMeta", // tp_name - sizeof(PyMessageMeta), // tp_basicsize + sizeof(CMessageClass), // tp_basicsize 0, // tp_itemsize (destructor)message_meta::Dealloc, // tp_dealloc 0, // tp_print @@ -419,16 +390,16 @@ PyTypeObject PyMessageMeta_Type = { message_meta::New, // tp_new }; -static PyMessageMeta* CheckMessageClass(PyTypeObject* cls) { - if (!PyObject_TypeCheck(cls, &PyMessageMeta_Type)) { +static CMessageClass* CheckMessageClass(PyTypeObject* cls) { + if (!PyObject_TypeCheck(cls, &CMessageClass_Type)) { PyErr_Format(PyExc_TypeError, "Class %s is not a Message", cls->tp_name); return NULL; } - return reinterpret_cast<PyMessageMeta*>(cls); + return reinterpret_cast<CMessageClass*>(cls); } static const Descriptor* GetMessageDescriptor(PyTypeObject* cls) { - PyMessageMeta* type = CheckMessageClass(cls); + CMessageClass* type = CheckMessageClass(cls); if (type == NULL) { return NULL; } @@ -783,9 +754,9 @@ namespace cmessage { PyDescriptorPool* GetDescriptorPoolForMessage(CMessage* message) { // No need to check the type: the type of instances of CMessage is always - // an instance of PyMessageMeta. Let's prove it with a debug-only check. + // an instance of CMessageClass. Let's prove it with a debug-only check. GOOGLE_DCHECK(PyObject_TypeCheck(message, &CMessage_Type)); - return reinterpret_cast<PyMessageMeta*>(Py_TYPE(message))->py_descriptor_pool; + return reinterpret_cast<CMessageClass*>(Py_TYPE(message))->py_descriptor_pool; } MessageFactory* GetFactoryForMessage(CMessage* message) { @@ -1090,6 +1061,10 @@ int InitAttributes(CMessage* self, PyObject* kwargs) { PyString_AsString(name)); return -1; } + if (value == Py_None) { + // field=None is the same as no field at all. + continue; + } if (descriptor->is_map()) { ScopedPyObjectPtr map(GetAttr(self, name)); const FieldDescriptor* value_descriptor = @@ -1220,9 +1195,9 @@ int InitAttributes(CMessage* self, PyObject* kwargs) { // Allocates an incomplete Python Message: the caller must fill self->message, // self->owner and eventually self->parent. -CMessage* NewEmptyMessage(PyObject* type, const Descriptor *descriptor) { +CMessage* NewEmptyMessage(CMessageClass* type) { CMessage* self = reinterpret_cast<CMessage*>( - PyType_GenericAlloc(reinterpret_cast<PyTypeObject*>(type), 0)); + PyType_GenericAlloc(&type->super.ht_type, 0)); if (self == NULL) { return NULL; } @@ -1242,7 +1217,7 @@ CMessage* NewEmptyMessage(PyObject* type, const Descriptor *descriptor) { // Creates a new C++ message and takes ownership. static PyObject* New(PyTypeObject* cls, PyObject* unused_args, PyObject* unused_kwargs) { - PyMessageMeta* type = CheckMessageClass(cls); + CMessageClass* type = CheckMessageClass(cls); if (type == NULL) { return NULL; } @@ -1258,8 +1233,7 @@ static PyObject* New(PyTypeObject* cls, return NULL; } - CMessage* self = NewEmptyMessage(reinterpret_cast<PyObject*>(type), - message_descriptor); + CMessage* self = NewEmptyMessage(type); if (self == NULL) { return NULL; } @@ -2023,10 +1997,34 @@ static PyObject* RegisterExtension(PyObject* cls, PyErr_SetString(PyExc_TypeError, "no extensions_by_number on class"); return NULL; } + ScopedPyObjectPtr number(PyObject_GetAttrString(extension_handle, "number")); if (number == NULL) { return NULL; } + + // If the extension was already registered by number, check that it is the + // same. + existing_extension = PyDict_GetItem(extensions_by_number.get(), number.get()); + if (existing_extension != NULL) { + const FieldDescriptor* existing_extension_descriptor = + GetExtensionDescriptor(existing_extension); + if (existing_extension_descriptor != descriptor) { + const Descriptor* msg_desc = GetMessageDescriptor( + reinterpret_cast<PyTypeObject*>(cls)); + PyErr_Format( + PyExc_ValueError, + "Extensions \"%s\" and \"%s\" both try to extend message type " + "\"%s\" with field number %ld.", + existing_extension_descriptor->full_name().c_str(), + descriptor->full_name().c_str(), + msg_desc->full_name().c_str(), + PyInt_AsLong(number.get())); + return NULL; + } + // Nothing else to do. + Py_RETURN_NONE; + } if (PyDict_SetItem(extensions_by_number.get(), number.get(), extension_handle) < 0) { return NULL; @@ -2166,6 +2164,12 @@ static PyObject* ListFields(CMessage* self) { return all_fields.release(); } +static PyObject* DiscardUnknownFields(CMessage* self) { + AssureWritable(self); + self->message->DiscardUnknownFields(); + Py_RETURN_NONE; +} + PyObject* FindInitializationErrors(CMessage* self) { Message* message = self->message; vector<string> errors; @@ -2309,14 +2313,13 @@ PyObject* InternalGetSubMessage( const Message& sub_message = reflection->GetMessage( *self->message, field_descriptor, pool->message_factory); - PyObject *message_class = cdescriptor_pool::GetMessageClass( + CMessageClass* message_class = cdescriptor_pool::GetMessageClass( pool, field_descriptor->message_type()); if (message_class == NULL) { return NULL; } - CMessage* cmsg = cmessage::NewEmptyMessage(message_class, - sub_message.GetDescriptor()); + CMessage* cmsg = cmessage::NewEmptyMessage(message_class); if (cmsg == NULL) { return NULL; } @@ -2585,6 +2588,8 @@ static PyMethodDef Methods[] = { "Clears a message field." }, { "CopyFrom", (PyCFunction)CopyFrom, METH_O, "Copies a protocol message into the current message." }, + { "DiscardUnknownFields", (PyCFunction)DiscardUnknownFields, METH_NOARGS, + "Discards the unknown fields." }, { "FindInitializationErrors", (PyCFunction)FindInitializationErrors, METH_NOARGS, "Finds unset required fields." }, @@ -2654,7 +2659,7 @@ PyObject* GetAttr(CMessage* self, PyObject* name) { const Descriptor* entry_type = field_descriptor->message_type(); const FieldDescriptor* value_type = entry_type->FindFieldByName("value"); if (value_type->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - PyObject* value_class = cdescriptor_pool::GetMessageClass( + CMessageClass* value_class = cdescriptor_pool::GetMessageClass( GetDescriptorPoolForMessage(self), value_type->message_type()); if (value_class == NULL) { return NULL; @@ -2677,7 +2682,7 @@ PyObject* GetAttr(CMessage* self, PyObject* name) { if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { PyObject* py_container = NULL; if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - PyObject *message_class = cdescriptor_pool::GetMessageClass( + CMessageClass* message_class = cdescriptor_pool::GetMessageClass( GetDescriptorPoolForMessage(self), field_descriptor->message_type()); if (message_class == NULL) { return NULL; @@ -2749,7 +2754,7 @@ int SetAttr(CMessage* self, PyObject* name, PyObject* value) { } // namespace cmessage PyTypeObject CMessage_Type = { - PyVarObject_HEAD_INIT(&PyMessageMeta_Type, 0) + PyVarObject_HEAD_INIT(&CMessageClass_Type, 0) FULL_MODULE_NAME ".CMessage", // tp_name sizeof(CMessage), // tp_basicsize 0, // tp_itemsize @@ -2864,12 +2869,12 @@ bool InitProto2MessageModule(PyObject *m) { // Initialize constants defined in this file. InitGlobals(); - PyMessageMeta_Type.tp_base = &PyType_Type; - if (PyType_Ready(&PyMessageMeta_Type) < 0) { + CMessageClass_Type.tp_base = &PyType_Type; + if (PyType_Ready(&CMessageClass_Type) < 0) { return false; } PyModule_AddObject(m, "MessageMeta", - reinterpret_cast<PyObject*>(&PyMessageMeta_Type)); + reinterpret_cast<PyObject*>(&CMessageClass_Type)); if (PyType_Ready(&CMessage_Type) < 0) { return false; @@ -3077,9 +3082,10 @@ bool InitProto2MessageModule(PyObject *m) { } // namespace protobuf static PyMethodDef ModuleMethods[] = { - {"SetAllowOversizeProtos", - (PyCFunction)google::protobuf::python::cmessage::SetAllowOversizeProtos, - METH_O, "Enable/disable oversize proto parsing."}, + {"SetAllowOversizeProtos", + (PyCFunction)google::protobuf::python::cmessage::SetAllowOversizeProtos, + METH_O, "Enable/disable oversize proto parsing."}, + { NULL, NULL} }; #if PY_MAJOR_VERSION >= 3 diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h index c2b62649..9dce198f 100644 --- a/python/google/protobuf/pyext/message.h +++ b/python/google/protobuf/pyext/message.h @@ -116,12 +116,43 @@ typedef struct CMessage { extern PyTypeObject CMessage_Type; + +// The (meta) type of all Messages classes. +// It allows us to cache some C++ pointers in the class object itself, they are +// faster to extract than from the type's dictionary. + +struct CMessageClass { + // This is how CPython subclasses C structures: the base structure must be + // the first member of the object. + PyHeapTypeObject super; + + // C++ descriptor of this message. + const Descriptor* message_descriptor; + + // Owned reference, used to keep the pointer above alive. + PyObject* py_message_descriptor; + + // The Python DescriptorPool used to create the class. It is needed to resolve + // fields descriptors, including extensions fields; its C++ MessageFactory is + // used to instantiate submessages. + // This can be different from DESCRIPTOR.file.pool, in the case of a custom + // DescriptorPool which defines new extensions. + // We own the reference, because it's important to keep the descriptors and + // factory alive. + PyDescriptorPool* py_descriptor_pool; + + PyObject* AsPyObject() { + return reinterpret_cast<PyObject*>(this); + } +}; + + namespace cmessage { // Internal function to create a new empty Message Python object, but with empty // pointers to the C++ objects. // The caller must fill self->message, self->owner and eventually self->parent. -CMessage* NewEmptyMessage(PyObject* type, const Descriptor* descriptor); +CMessage* NewEmptyMessage(CMessageClass* type); // Release a submessage from its proto tree, making it a new top-level messgae. // A new message will be created if this is a read-only default instance. diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc index b01123b4..4f339e77 100644 --- a/python/google/protobuf/pyext/repeated_composite_container.cc +++ b/python/google/protobuf/pyext/repeated_composite_container.cc @@ -107,8 +107,7 @@ static int UpdateChildMessages(RepeatedCompositeContainer* self) { 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->subclass_init, - sub_message.GetDescriptor()); + CMessage* cmsg = cmessage::NewEmptyMessage(self->child_message_class); ScopedPyObjectPtr py_cmsg(reinterpret_cast<PyObject*>(cmsg)); if (cmsg == NULL) { return -1; @@ -140,8 +139,7 @@ static PyObject* AddToAttached(RepeatedCompositeContainer* self, Message* sub_message = message->GetReflection()->AddMessage(message, self->parent_field_descriptor); - CMessage* cmsg = cmessage::NewEmptyMessage(self->subclass_init, - sub_message->GetDescriptor()); + CMessage* cmsg = cmessage::NewEmptyMessage(self->child_message_class); if (cmsg == NULL) return NULL; @@ -168,7 +166,7 @@ static PyObject* AddToReleased(RepeatedCompositeContainer* self, // Create a new Message detached from the rest. PyObject* py_cmsg = PyEval_CallObjectWithKeywords( - self->subclass_init, NULL, kwargs); + self->child_message_class->AsPyObject(), NULL, kwargs); if (py_cmsg == NULL) return NULL; @@ -506,7 +504,7 @@ int SetOwner(RepeatedCompositeContainer* self, PyObject *NewContainer( CMessage* parent, const FieldDescriptor* parent_field_descriptor, - PyObject *concrete_class) { + CMessageClass* concrete_class) { if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) { return NULL; } @@ -523,7 +521,7 @@ PyObject *NewContainer( self->parent_field_descriptor = parent_field_descriptor; self->owner = parent->owner; Py_INCREF(concrete_class); - self->subclass_init = concrete_class; + self->child_message_class = concrete_class; self->child_messages = PyList_New(0); return reinterpret_cast<PyObject*>(self); @@ -531,7 +529,7 @@ PyObject *NewContainer( static void Dealloc(RepeatedCompositeContainer* self) { Py_CLEAR(self->child_messages); - Py_CLEAR(self->subclass_init); + 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(); diff --git a/python/google/protobuf/pyext/repeated_composite_container.h b/python/google/protobuf/pyext/repeated_composite_container.h index 442ce7e3..25463037 100644 --- a/python/google/protobuf/pyext/repeated_composite_container.h +++ b/python/google/protobuf/pyext/repeated_composite_container.h @@ -58,6 +58,7 @@ using internal::shared_ptr; namespace python { struct CMessage; +struct CMessageClass; // A RepeatedCompositeContainer can be in one of two states: attached // or released. @@ -94,8 +95,8 @@ typedef struct RepeatedCompositeContainer { // calling Clear() or ClearField() on the parent. Message* message; - // A callable that is used to create new child messages. - PyObject* subclass_init; + // The type used to create new child messages. + CMessageClass* child_message_class; // A list of child messages. PyObject* child_messages; @@ -110,7 +111,7 @@ namespace repeated_composite_container { PyObject *NewContainer( CMessage* parent, const FieldDescriptor* parent_field_descriptor, - PyObject *concrete_class); + CMessageClass *child_message_class); // Appends a new CMessage to the container and returns it. The // CMessage is initialized using the content of kwargs. diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py index a6f41ca8..6f1e3c8b 100755 --- a/python/google/protobuf/text_format.py +++ b/python/google/protobuf/text_format.py @@ -99,7 +99,7 @@ class TextWriter(object): def MessageToString(message, as_utf8=False, as_one_line=False, pointy_brackets=False, use_index_order=False, - float_format=None): + float_format=None, use_field_number=False): """Convert protobuf message to text format. Floating point values can be formatted compactly with 15 digits of @@ -118,15 +118,16 @@ def MessageToString(message, as_utf8=False, as_one_line=False, 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_field_number: If True, print field numbers instead of names. Returns: A string of the text formatted protocol buffer message. """ out = TextWriter(as_utf8) - PrintMessage(message, out, as_utf8=as_utf8, as_one_line=as_one_line, - pointy_brackets=pointy_brackets, - use_index_order=use_index_order, - float_format=float_format) + printer = _Printer(out, 0, as_utf8, as_one_line, + pointy_brackets, use_index_order, float_format, + use_field_number) + printer.PrintMessage(message) result = out.getvalue() out.close() if as_one_line: @@ -142,133 +143,187 @@ def _IsMapEntry(field): def PrintMessage(message, out, indent=0, as_utf8=False, as_one_line=False, pointy_brackets=False, use_index_order=False, - float_format=None): - fields = message.ListFields() - if use_index_order: - fields.sort(key=lambda x: 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 - # entire tree. Unfortunately this would take significant refactoring - # of this file to work around. - # - # TODO(haberman): refactor and optimize if this becomes an issue. - entry_submsg = field.message_type._concrete_class( - key=key, value=value[key]) - PrintField(field, entry_submsg, out, indent, as_utf8, as_one_line, - pointy_brackets=pointy_brackets, - use_index_order=use_index_order, float_format=float_format) - elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED: - for element in value: - PrintField(field, element, out, indent, as_utf8, as_one_line, - pointy_brackets=pointy_brackets, - use_index_order=use_index_order, - float_format=float_format) - else: - PrintField(field, value, out, indent, as_utf8, as_one_line, - pointy_brackets=pointy_brackets, - use_index_order=use_index_order, - float_format=float_format) + float_format=None, use_field_number=False): + printer = _Printer(out, indent, as_utf8, as_one_line, + pointy_brackets, use_index_order, float_format, + use_field_number) + printer.PrintMessage(message) def PrintField(field, value, out, indent=0, as_utf8=False, as_one_line=False, pointy_brackets=False, use_index_order=False, float_format=None): - """Print a single field name/value pair. For repeated fields, the value - should be a single element. - """ - - out.write(' ' * indent) - if field.is_extension: - out.write('[') - if (field.containing_type.GetOptions().message_set_wire_format and - field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and - field.label == descriptor.FieldDescriptor.LABEL_OPTIONAL): - out.write(field.message_type.full_name) - else: - out.write(field.full_name) - out.write(']') - elif field.type == descriptor.FieldDescriptor.TYPE_GROUP: - # For groups, use the capitalized name. - out.write(field.message_type.name) - else: - out.write(field.name) - - if 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(': ') - - PrintFieldValue(field, value, out, indent, as_utf8, as_one_line, - pointy_brackets=pointy_brackets, - use_index_order=use_index_order, - float_format=float_format) - if as_one_line: - out.write(' ') - else: - out.write('\n') + """Print a single field name/value pair.""" + printer = _Printer(out, indent, as_utf8, as_one_line, + pointy_brackets, use_index_order, float_format) + printer.PrintField(field, value) def PrintFieldValue(field, value, out, indent=0, as_utf8=False, as_one_line=False, pointy_brackets=False, use_index_order=False, float_format=None): - """Print a single field value (not including name). For repeated fields, - the value should be a single element.""" + """Print a single field value (not including name).""" + printer = _Printer(out, indent, as_utf8, as_one_line, + pointy_brackets, use_index_order, float_format) + printer.PrintFieldValue(field, value) - if pointy_brackets: - openb = '<' - closeb = '>' - else: - openb = '{' - closeb = '}' - - if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: - if as_one_line: - out.write(' %s ' % openb) - PrintMessage(value, out, indent, as_utf8, as_one_line, - pointy_brackets=pointy_brackets, - use_index_order=use_index_order, - float_format=float_format) - out.write(closeb) - else: - out.write(' %s\n' % openb) - PrintMessage(value, out, indent + 2, as_utf8, as_one_line, - pointy_brackets=pointy_brackets, - use_index_order=use_index_order, - float_format=float_format) - out.write(' ' * indent + closeb) - elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM: - enum_value = field.enum_type.values_by_number.get(value, None) - if enum_value is not None: - out.write(enum_value.name) + +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): + """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. + + Args: + out: To record the text format result. + indent: The indent level for pretty print. + as_utf8: Produce text output in UTF8 format. + as_one_line: Don't introduce newlines between fields. + 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_field_number: If True, print field numbers instead of names. + """ + self.out = out + self.indent = indent + self.as_utf8 = as_utf8 + self.as_one_line = as_one_line + self.pointy_brackets = pointy_brackets + self.use_index_order = use_index_order + self.float_format = float_format + self.use_field_number = use_field_number + + def PrintMessage(self, message): + """Convert protobuf message to text format. + + Args: + message: The protocol buffers message. + """ + fields = message.ListFields() + if self.use_index_order: + fields.sort(key=lambda x: 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 + # entire tree. Unfortunately this would take significant refactoring + # of this file to work around. + # + # TODO(haberman): refactor and optimize if this becomes an issue. + entry_submsg = field.message_type._concrete_class( + 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) + else: + self.PrintField(field, value) + + def PrintField(self, field, value): + """Print a single field name/value pair.""" + out = self.out + out.write(' ' * self.indent) + if self.use_field_number: + out.write(str(field.number)) else: - out.write(str(value)) - elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING: - out.write('\"') - if isinstance(value, six.text_type): - out_value = value.encode('utf-8') + if field.is_extension: + out.write('[') + if (field.containing_type.GetOptions().message_set_wire_format and + field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and + field.label == descriptor.FieldDescriptor.LABEL_OPTIONAL): + out.write(field.message_type.full_name) + else: + out.write(field.full_name) + out.write(']') + elif field.type == descriptor.FieldDescriptor.TYPE_GROUP: + # For groups, use the capitalized name. + out.write(field.message_type.name) + else: + out.write(field.name) + + if 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(': ') + + self.PrintFieldValue(field, value) + if self.as_one_line: + out.write(' ') else: - out_value = value - if field.type == descriptor.FieldDescriptor.TYPE_BYTES: - # We need to escape non-UTF8 chars in TYPE_BYTES field. - out_as_utf8 = False + out.write('\n') + + def PrintFieldValue(self, field, value): + """Print a single field value (not including name). + + For repeated fields, the value should be a single element. + + Args: + field: The descriptor of the field to be printed. + value: The value of the field. + """ + out = self.out + if self.pointy_brackets: + openb = '<' + closeb = '>' else: - out_as_utf8 = as_utf8 - out.write(text_encoding.CEscape(out_value, out_as_utf8)) - out.write('\"') - elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL: - if value: - out.write('true') + openb = '{' + closeb = '}' + + if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + if self.as_one_line: + out.write(' %s ' % openb) + self.PrintMessage(value) + out.write(closeb) + else: + out.write(' %s\n' % openb) + self.indent += 2 + self.PrintMessage(value) + self.indent -= 2 + out.write(' ' * self.indent + closeb) + elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM: + enum_value = field.enum_type.values_by_number.get(value, None) + if enum_value is not None: + out.write(enum_value.name) + else: + out.write(str(value)) + elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING: + out.write('\"') + if isinstance(value, six.text_type): + 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. + out_as_utf8 = False + else: + out_as_utf8 = self.as_utf8 + out.write(text_encoding.CEscape(out_value, out_as_utf8)) + out.write('\"') + elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL: + if 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)) else: - out.write('false') - elif field.cpp_type in _FLOAT_TYPES and float_format is not None: - out.write('{1:{0}}'.format(float_format, value)) - else: - out.write(str(value)) + out.write(str(value)) -def Parse(text, message, allow_unknown_extension=False): +def Parse(text, message, + allow_unknown_extension=False, allow_field_number=False): """Parses an text representation of a protocol message into a message. Args: @@ -276,6 +331,7 @@ def Parse(text, message, allow_unknown_extension=False): 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. Returns: The same message passed as argument. @@ -285,10 +341,12 @@ def Parse(text, message, allow_unknown_extension=False): """ if not isinstance(text, str): text = text.decode('utf-8') - return ParseLines(text.split('\n'), message, allow_unknown_extension) + return ParseLines(text.split('\n'), message, allow_unknown_extension, + allow_field_number) -def Merge(text, message, allow_unknown_extension=False): +def Merge(text, message, allow_unknown_extension=False, + allow_field_number=False): """Parses an text representation of a protocol message into a message. Like Parse(), but allows repeated values for a non-repeated field, and uses @@ -299,6 +357,7 @@ def Merge(text, message, allow_unknown_extension=False): 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. Returns: The same message passed as argument. @@ -306,10 +365,12 @@ def Merge(text, message, allow_unknown_extension=False): Raises: ParseError: On text parsing problems. """ - return MergeLines(text.split('\n'), message, allow_unknown_extension) + return MergeLines(text.split('\n'), message, allow_unknown_extension, + allow_field_number) -def ParseLines(lines, message, allow_unknown_extension=False): +def ParseLines(lines, message, allow_unknown_extension=False, + allow_field_number=False): """Parses an text representation of a protocol message into a message. Args: @@ -317,6 +378,7 @@ def ParseLines(lines, message, allow_unknown_extension=False): 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. Returns: The same message passed as argument. @@ -324,11 +386,12 @@ def ParseLines(lines, message, allow_unknown_extension=False): Raises: ParseError: On text parsing problems. """ - _ParseOrMerge(lines, message, False, allow_unknown_extension) - return message + parser = _Parser(allow_unknown_extension, allow_field_number) + return parser.ParseLines(lines, message) -def MergeLines(lines, message, allow_unknown_extension=False): +def MergeLines(lines, message, allow_unknown_extension=False, + allow_field_number=False): """Parses an text representation of a protocol message into a message. Args: @@ -336,6 +399,7 @@ def MergeLines(lines, message, allow_unknown_extension=False): 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. Returns: The same message passed as argument. @@ -343,146 +407,272 @@ def MergeLines(lines, message, allow_unknown_extension=False): Raises: ParseError: On text parsing problems. """ - _ParseOrMerge(lines, message, True, allow_unknown_extension) - return message + parser = _Parser(allow_unknown_extension, allow_field_number) + return parser.MergeLines(lines, message) -def _ParseOrMerge(lines, - message, - allow_multiple_scalars, - allow_unknown_extension=False): - """Converts an text representation of a protocol message into a message. +class _Parser(object): + """Text format parser for protocol message.""" - Args: - lines: Lines of a message's text representation. - message: A protocol buffer message to merge into. - allow_multiple_scalars: Determines if repeated values for a non-repeated - field are permitted, e.g., the string "foo: 1 foo: 2" for a - required/optional field named "foo". - allow_unknown_extension: if True, skip over missing extensions and keep - parsing + def __init__(self, allow_unknown_extension=False, allow_field_number=False): + self.allow_unknown_extension = allow_unknown_extension + self.allow_field_number = allow_field_number - Raises: - ParseError: On text parsing problems. - """ - tokenizer = _Tokenizer(lines) - while not tokenizer.AtEnd(): - _MergeField(tokenizer, message, allow_multiple_scalars, - allow_unknown_extension) + def ParseFromString(self, text, message): + """Parses an 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) + def ParseLines(self, lines, message): + """Parses an text representation of a protocol message into a message.""" + self._allow_multiple_scalars = False + self._ParseOrMerge(lines, message) + return message -def _MergeField(tokenizer, - message, - allow_multiple_scalars, - allow_unknown_extension=False): - """Merges a single protocol message field into a message. + def MergeFromString(self, text, message): + """Merges an text representation of a protocol message into a message.""" + return self._MergeLines(text.split('\n'), message) - Args: - tokenizer: A tokenizer to parse the field name and values. - message: A protocol message to record the data. - allow_multiple_scalars: Determines if repeated values for a non-repeated - field are permitted, e.g., the string "foo: 1 foo: 2" for a - required/optional field named "foo". - allow_unknown_extension: if True, skip over missing extensions and keep - parsing. + def MergeLines(self, lines, message): + """Merges an text representation of a protocol message into a message.""" + self._allow_multiple_scalars = True + self._ParseOrMerge(lines, message) + return message - Raises: - ParseError: In case of text parsing problems. - """ - message_descriptor = message.DESCRIPTOR - if (hasattr(message_descriptor, 'syntax') and - message_descriptor.syntax == 'proto3'): - # Proto3 doesn't represent presence so we can't test if multiple - # scalars have occurred. We have to allow them. - allow_multiple_scalars = True - if tokenizer.TryConsume('['): - name = [tokenizer.ConsumeIdentifier()] - while tokenizer.TryConsume('.'): - name.append(tokenizer.ConsumeIdentifier()) - name = '.'.join(name) - - if not message_descriptor.is_extendable: - raise tokenizer.ParseErrorPreviousToken( - 'Message type "%s" does not have extensions.' % - message_descriptor.full_name) - # pylint: disable=protected-access - field = message.Extensions._FindExtensionByName(name) - # pylint: enable=protected-access - if not field: - if allow_unknown_extension: - field = None - else: - raise tokenizer.ParseErrorPreviousToken( - 'Extension "%s" not registered.' % name) - elif message_descriptor != field.containing_type: - raise tokenizer.ParseErrorPreviousToken( - 'Extension "%s" does not extend message type "%s".' % ( - name, message_descriptor.full_name)) + def _ParseOrMerge(self, lines, message): + """Converts an text representation of a protocol message into a message. - tokenizer.Consume(']') + Args: + lines: Lines of a message's text representation. + message: A protocol buffer message to merge into. - else: - name = tokenizer.ConsumeIdentifier() - field = message_descriptor.fields_by_name.get(name, None) - - # 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 not field: - field = message_descriptor.fields_by_name.get(name.lower(), None) - if field and field.type != descriptor.FieldDescriptor.TYPE_GROUP: - field = None - - if (field and field.type == descriptor.FieldDescriptor.TYPE_GROUP and - field.message_type.name != name): - field = None - - if not field: - raise tokenizer.ParseErrorPreviousToken( - 'Message type "%s" has no field named "%s".' % ( - message_descriptor.full_name, name)) - - if field: - if not allow_multiple_scalars and field.containing_oneof: - # Check if there's a different field set in this oneof. - # Note that we ignore the case if the same field was set before, and we - # apply allow_multiple_scalars to non-scalar fields as well. - which_oneof = message.WhichOneof(field.containing_oneof.name) - if which_oneof is not None and which_oneof != field.name: + Raises: + ParseError: On text parsing problems. + """ + tokenizer = _Tokenizer(lines) + while not tokenizer.AtEnd(): + self._MergeField(tokenizer, message) + + def _MergeField(self, tokenizer, message): + """Merges a single protocol message field into a message. + + Args: + tokenizer: A tokenizer to parse the field name and values. + message: A protocol message to record the data. + + Raises: + ParseError: In case of text parsing problems. + """ + message_descriptor = message.DESCRIPTOR + if (hasattr(message_descriptor, 'syntax') and + message_descriptor.syntax == 'proto3'): + # Proto3 doesn't represent presence so we can't test if multiple + # scalars have occurred. We have to allow them. + self._allow_multiple_scalars = True + if tokenizer.TryConsume('['): + name = [tokenizer.ConsumeIdentifier()] + while tokenizer.TryConsume('.'): + name.append(tokenizer.ConsumeIdentifier()) + name = '.'.join(name) + + if not message_descriptor.is_extendable: + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" does not have extensions.' % + message_descriptor.full_name) + # pylint: disable=protected-access + field = message.Extensions._FindExtensionByName(name) + # pylint: enable=protected-access + if not field: + if self.allow_unknown_extension: + field = None + else: + raise tokenizer.ParseErrorPreviousToken( + 'Extension "%s" not registered.' % name) + elif message_descriptor != field.containing_type: raise tokenizer.ParseErrorPreviousToken( - 'Field "%s" is specified along with field "%s", another member of ' - 'oneof "%s" for message type "%s".' % ( - field.name, which_oneof, field.containing_oneof.name, - message_descriptor.full_name)) + 'Extension "%s" does not extend message type "%s".' % ( + name, message_descriptor.full_name)) + + tokenizer.Consume(']') - if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: - tokenizer.TryConsume(':') - merger = _MergeMessageField else: - tokenizer.Consume(':') - merger = _MergeScalarField - - 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, allow_multiple_scalars, - allow_unknown_extension) - if tokenizer.TryConsume(']'): break - tokenizer.Consume(',') + name = tokenizer.ConsumeIdentifier() + if self.allow_field_number and name.isdigit(): + number = ParseInteger(name, True, True) + field = message_descriptor.fields_by_number.get(number, None) + if not field and message_descriptor.is_extendable: + field = message.Extensions._FindExtensionByNumber(number) + else: + field = message_descriptor.fields_by_name.get(name, None) + + # 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 not field: + field = message_descriptor.fields_by_name.get(name.lower(), None) + if field and field.type != descriptor.FieldDescriptor.TYPE_GROUP: + field = None + + if (field and field.type == descriptor.FieldDescriptor.TYPE_GROUP and + field.message_type.name != name): + field = None + + if not field: + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" has no field named "%s".' % ( + message_descriptor.full_name, name)) + + if field: + if not self._allow_multiple_scalars and field.containing_oneof: + # Check if there's a different field set in this oneof. + # Note that we ignore the case if the same field was set before, and we + # apply _allow_multiple_scalars to non-scalar fields as well. + which_oneof = message.WhichOneof(field.containing_oneof.name) + if which_oneof is not None and which_oneof != field.name: + raise tokenizer.ParseErrorPreviousToken( + 'Field "%s" is specified along with field "%s", another member ' + 'of oneof "%s" for message type "%s".' % ( + field.name, which_oneof, field.containing_oneof.name, + message_descriptor.full_name)) + + if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + tokenizer.TryConsume(':') + merger = self._MergeMessageField + else: + tokenizer.Consume(':') + merger = self._MergeScalarField + + 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(',') + + else: + merger(tokenizer, message, field) + + else: # Proto field is unknown. + assert self.allow_unknown_extension + _SkipFieldContents(tokenizer) + + # For historical reasons, fields may optionally be separated by commas or + # semicolons. + if not tokenizer.TryConsume(','): + tokenizer.TryConsume(';') + + def _MergeMessageField(self, tokenizer, message, field): + """Merges a single scalar field into a message. + + Args: + tokenizer: A tokenizer to parse the field value. + message: The message of which field is a member. + field: The descriptor of the field to be merged. + + Raises: + ParseError: In case of text parsing problems. + """ + is_map_entry = _IsMapEntry(field) + if tokenizer.TryConsume('<'): + end_token = '>' else: - merger(tokenizer, message, field, allow_multiple_scalars, - allow_unknown_extension) + tokenizer.Consume('{') + end_token = '}' + + if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + if field.is_extension: + sub_message = message.Extensions[field].add() + elif is_map_entry: + # pylint: disable=protected-access + sub_message = field.message_type._concrete_class() + else: + sub_message = getattr(message, field.name).add() + else: + if field.is_extension: + sub_message = message.Extensions[field] + else: + sub_message = getattr(message, field.name) + sub_message.SetInParent() + + while not tokenizer.TryConsume(end_token): + if tokenizer.AtEnd(): + raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % (end_token,)) + self._MergeField(tokenizer, sub_message) + + if is_map_entry: + value_cpptype = field.message_type.fields_by_name['value'].cpp_type + if value_cpptype == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + value = getattr(message, field.name)[sub_message.key] + value.MergeFrom(sub_message.value) + else: + getattr(message, field.name)[sub_message.key] = sub_message.value - else: # Proto field is unknown. - assert allow_unknown_extension - _SkipFieldContents(tokenizer) + def _MergeScalarField(self, tokenizer, message, field): + """Merges a single scalar field into a message. - # For historical reasons, fields may optionally be separated by commas or - # semicolons. - if not tokenizer.TryConsume(','): - tokenizer.TryConsume(';') + Args: + tokenizer: A tokenizer to parse the field value. + message: A protocol message to record the data. + field: The descriptor of the field to be merged. + + Raises: + ParseError: In case of text parsing problems. + RuntimeError: On runtime errors. + """ + _ = self.allow_unknown_extension + value = None + + if field.type in (descriptor.FieldDescriptor.TYPE_INT32, + descriptor.FieldDescriptor.TYPE_SINT32, + descriptor.FieldDescriptor.TYPE_SFIXED32): + value = tokenizer.ConsumeInt32() + elif field.type in (descriptor.FieldDescriptor.TYPE_INT64, + descriptor.FieldDescriptor.TYPE_SINT64, + descriptor.FieldDescriptor.TYPE_SFIXED64): + value = tokenizer.ConsumeInt64() + elif field.type in (descriptor.FieldDescriptor.TYPE_UINT32, + descriptor.FieldDescriptor.TYPE_FIXED32): + value = tokenizer.ConsumeUint32() + elif field.type in (descriptor.FieldDescriptor.TYPE_UINT64, + descriptor.FieldDescriptor.TYPE_FIXED64): + value = tokenizer.ConsumeUint64() + elif field.type in (descriptor.FieldDescriptor.TYPE_FLOAT, + descriptor.FieldDescriptor.TYPE_DOUBLE): + value = tokenizer.ConsumeFloat() + elif field.type == descriptor.FieldDescriptor.TYPE_BOOL: + value = tokenizer.ConsumeBool() + elif field.type == descriptor.FieldDescriptor.TYPE_STRING: + value = tokenizer.ConsumeString() + elif field.type == descriptor.FieldDescriptor.TYPE_BYTES: + value = tokenizer.ConsumeByteString() + elif field.type == descriptor.FieldDescriptor.TYPE_ENUM: + value = tokenizer.ConsumeEnum(field) + else: + raise RuntimeError('Unknown field type %d' % field.type) + + if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + if field.is_extension: + message.Extensions[field].append(value) + else: + getattr(message, field.name).append(value) + 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)) + else: + message.Extensions[field] = value + else: + 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)) + else: + setattr(message, field.name, value) def _SkipFieldContents(tokenizer): @@ -555,10 +745,10 @@ def _SkipFieldValue(tokenizer): Raises: ParseError: In case an invalid field value is found. """ - # String tokens can come in multiple adjacent string literals. + # String/bytes tokens can come in multiple adjacent string literals. # If we can consume one, consume as many as we can. - if tokenizer.TryConsumeString(): - while tokenizer.TryConsumeString(): + if tokenizer.TryConsumeByteString(): + while tokenizer.TryConsumeByteString(): pass return @@ -569,132 +759,6 @@ def _SkipFieldValue(tokenizer): raise ParseError('Invalid field value: ' + tokenizer.token) -def _MergeMessageField(tokenizer, message, field, allow_multiple_scalars, - allow_unknown_extension): - """Merges a single scalar field into a message. - - Args: - tokenizer: A tokenizer to parse the field value. - message: The message of which field is a member. - field: The descriptor of the field to be merged. - allow_multiple_scalars: Determines if repeated values for a non-repeated - field are permitted, e.g., the string "foo: 1 foo: 2" for a - required/optional field named "foo". - allow_unknown_extension: if True, skip over missing extensions and keep - parsing. - - Raises: - ParseError: In case of text parsing problems. - """ - is_map_entry = _IsMapEntry(field) - - if tokenizer.TryConsume('<'): - end_token = '>' - else: - tokenizer.Consume('{') - end_token = '}' - - if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: - if field.is_extension: - sub_message = message.Extensions[field].add() - elif is_map_entry: - # pylint: disable=protected-access - sub_message = field.message_type._concrete_class() - else: - sub_message = getattr(message, field.name).add() - else: - if field.is_extension: - sub_message = message.Extensions[field] - else: - sub_message = getattr(message, field.name) - sub_message.SetInParent() - - while not tokenizer.TryConsume(end_token): - if tokenizer.AtEnd(): - raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % (end_token,)) - _MergeField(tokenizer, sub_message, allow_multiple_scalars, - allow_unknown_extension) - - if is_map_entry: - value_cpptype = field.message_type.fields_by_name['value'].cpp_type - if value_cpptype == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: - value = getattr(message, field.name)[sub_message.key] - value.MergeFrom(sub_message.value) - else: - getattr(message, field.name)[sub_message.key] = sub_message.value - - -def _MergeScalarField(tokenizer, message, field, allow_multiple_scalars, - allow_unknown_extension): - """Merges a single scalar field into a message. - - Args: - tokenizer: A tokenizer to parse the field value. - message: A protocol message to record the data. - field: The descriptor of the field to be merged. - allow_multiple_scalars: Determines if repeated values for a non-repeated - field are permitted, e.g., the string "foo: 1 foo: 2" for a - required/optional field named "foo". - allow_unknown_extension: Unused, just here for consistency with - _MergeMessageField. - - Raises: - ParseError: In case of text parsing problems. - RuntimeError: On runtime errors. - """ - _ = allow_unknown_extension - value = None - - if field.type in (descriptor.FieldDescriptor.TYPE_INT32, - descriptor.FieldDescriptor.TYPE_SINT32, - descriptor.FieldDescriptor.TYPE_SFIXED32): - value = tokenizer.ConsumeInt32() - elif field.type in (descriptor.FieldDescriptor.TYPE_INT64, - descriptor.FieldDescriptor.TYPE_SINT64, - descriptor.FieldDescriptor.TYPE_SFIXED64): - value = tokenizer.ConsumeInt64() - elif field.type in (descriptor.FieldDescriptor.TYPE_UINT32, - descriptor.FieldDescriptor.TYPE_FIXED32): - value = tokenizer.ConsumeUint32() - elif field.type in (descriptor.FieldDescriptor.TYPE_UINT64, - descriptor.FieldDescriptor.TYPE_FIXED64): - value = tokenizer.ConsumeUint64() - elif field.type in (descriptor.FieldDescriptor.TYPE_FLOAT, - descriptor.FieldDescriptor.TYPE_DOUBLE): - value = tokenizer.ConsumeFloat() - elif field.type == descriptor.FieldDescriptor.TYPE_BOOL: - value = tokenizer.ConsumeBool() - elif field.type == descriptor.FieldDescriptor.TYPE_STRING: - value = tokenizer.ConsumeString() - elif field.type == descriptor.FieldDescriptor.TYPE_BYTES: - value = tokenizer.ConsumeByteString() - elif field.type == descriptor.FieldDescriptor.TYPE_ENUM: - value = tokenizer.ConsumeEnum(field) - else: - raise RuntimeError('Unknown field type %d' % field.type) - - if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: - if field.is_extension: - message.Extensions[field].append(value) - else: - getattr(message, field.name).append(value) - else: - if field.is_extension: - if not 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)) - else: - message.Extensions[field] = value - else: - if not 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)) - else: - setattr(message, field.name, value) - - class _Tokenizer(object): """Protocol buffer text representation tokenizer. @@ -925,9 +989,9 @@ class _Tokenizer(object): self.NextToken() return result - def TryConsumeString(self): + def TryConsumeByteString(self): try: - self.ConsumeString() + self.ConsumeByteString() return True except ParseError: return False diff --git a/ruby/Gemfile.lock b/ruby/Gemfile.lock index 27e57506..d0eb9cc4 100644 --- a/ruby/Gemfile.lock +++ b/ruby/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - google-protobuf (3.0.0.alpha.5.0) + google-protobuf (3.0.0.alpha.5.0.5) GEM remote: https://rubygems.org/ diff --git a/ruby/README.md b/ruby/README.md index 16474322..f28e05a7 100644 --- a/ruby/README.md +++ b/ruby/README.md @@ -32,23 +32,25 @@ documentation may be found in the RubyDoc comments (`call-seq` tags) in the source, and we plan to release separate, more detailed, documentation at a later date. - require 'google/protobuf' +```ruby +require 'google/protobuf' - # generated from my_proto_types.proto with protoc: - # $ protoc --ruby_out=. my_proto_types.proto - require 'my_proto_types' +# generated from my_proto_types.proto with protoc: +# $ protoc --ruby_out=. my_proto_types.proto +require 'my_proto_types' - mymessage = MyTestMessage.new(:field1 => 42, :field2 => ["a", "b", "c"]) - mymessage.field1 = 43 - mymessage.field2.push("d") - mymessage.field3 = SubMessage.new(:foo => 100) +mymessage = MyTestMessage.new(:field1 => 42, :field2 => ["a", "b", "c"]) +mymessage.field1 = 43 +mymessage.field2.push("d") +mymessage.field3 = SubMessage.new(:foo => 100) - encoded_data = MyTestMessage.encode(mymessage) - decoded = MyTestMessage.decode(encoded_data) - assert decoded == mymessage +encoded_data = MyTestMessage.encode(mymessage) +decoded = MyTestMessage.decode(encoded_data) +assert decoded == mymessage - puts "JSON:" - puts MyTestMessage.encode_json(mymessage) +puts "JSON:" +puts MyTestMessage.encode_json(mymessage) +``` Installation from Source (Building Gem) --------------------------------------- diff --git a/ruby/Rakefile b/ruby/Rakefile index 8eb7a2df..fa29c315 100644 --- a/ruby/Rakefile +++ b/ruby/Rakefile @@ -5,6 +5,40 @@ require "rake/testtask" spec = Gem::Specification.load("google-protobuf.gemspec") +well_known_protos = %w[ + 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 +] + +# These are omitted for now because we don't support proto2. +proto2_protos = %w[ + google/protobuf/descriptor.proto + google/protobuf/compiler/plugin.proto +] + +genproto_output = [] + +# We won't have access to .. from within docker, but the proto files +# will be there, thanks to the :genproto rule dependency for gem:native. +unless ENV['IN_DOCKER'] == 'true' + well_known_protos.each do |proto_file| + input_file = "../src/" + proto_file + output_file = "lib/" + proto_file.sub(/\.proto$/, ".rb") + genproto_output << output_file + file output_file => input_file do |file_task| + sh "../src/protoc -I../src --ruby_out=lib #{input_file}" + end + end +end + if RUBY_PLATFORM == "java" if `which mvn` == '' raise ArgumentError, "maven needs to be installed" @@ -30,37 +64,16 @@ else task 'gem:windows' do require 'rake_compiler_dock' - RakeCompilerDock.sh "bundle && rake cross native gem RUBY_CC_VERSION=2.3.0:2.2.2:2.1.6" + RakeCompilerDock.sh "bundle && IN_DOCKER=true rake cross native gem RUBY_CC_VERSION=2.3.0:2.2.2:2.1.5:2.0.0" end -end - -well_known_protos = %w[ - 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 -] - -# These are omitted for now because we don't support proto2. -proto2_protos = %w[ - google/protobuf/descriptor.proto - google/protobuf/compiler/plugin.proto -] - -genproto_output = [] -well_known_protos.each do |proto_file| - input_file = "../src/" + proto_file - output_file = "lib/" + proto_file.sub(/\.proto$/, ".rb") - genproto_output << output_file - file output_file => input_file do |file_task| - sh "../src/protoc -I../src --ruby_out=lib #{input_file}" + if RUBY_PLATFORM =~ /darwin/ + task 'gem:native' do + system "rake genproto" + system "rake cross native gem RUBY_CC_VERSION=2.3.0:2.2.2:2.1.5:2.0.0" + end + else + task 'gem:native' => [:genproto, 'gem:windows'] end end diff --git a/ruby/ext/google/protobuf_c/defs.c b/ruby/ext/google/protobuf_c/defs.c index 96ef4953..7e93bafb 100644 --- a/ruby/ext/google/protobuf_c/defs.c +++ b/ruby/ext/google/protobuf_c/defs.c @@ -255,6 +255,10 @@ void Descriptor_free(void* _self) { 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); } @@ -278,6 +282,7 @@ VALUE Descriptor_alloc(VALUE klass) { 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(); return ret; } diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c index c2c369eb..f6bea50f 100644 --- a/ruby/ext/google/protobuf_c/encode_decode.c +++ b/ruby/ext/google/protobuf_c/encode_decode.c @@ -656,7 +656,6 @@ static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) { #define STACK_ENV_STACKBYTES 4096 typedef struct { upb_env env; - upb_seededalloc alloc; const char* ruby_error_template; char allocbuf[STACK_ENV_STACKBYTES]; } stackenv; @@ -681,16 +680,12 @@ static bool env_error_func(void* ud, const upb_status* status) { static void stackenv_init(stackenv* se, const char* errmsg) { se->ruby_error_template = errmsg; - upb_env_init(&se->env); - upb_seededalloc_init(&se->alloc, &se->allocbuf, STACK_ENV_STACKBYTES); - upb_env_setallocfunc( - &se->env, upb_seededalloc_getallocfunc(&se->alloc), &se->alloc); + 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); - upb_seededalloc_uninit(&se->alloc); } /* @@ -1130,13 +1125,23 @@ static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) { return desc->pb_serialize_handlers; } -static const upb_handlers* msgdef_json_serialize_handlers(Descriptor* desc) { - if (desc->json_serialize_handlers == NULL) { - desc->json_serialize_handlers = - upb_json_printer_newhandlers( - desc->msgdef, &desc->json_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; } - return desc->json_serialize_handlers; } /* @@ -1181,16 +1186,33 @@ VALUE Message_encode(VALUE klass, VALUE msg_rb) { * * Encodes the given message object into its serialized JSON representation. */ -VALUE Message_encode_json(VALUE klass, VALUE msg_rb) { +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; 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); + } + stringsink_init(&sink); { const upb_handlers* serialize_handlers = - msgdef_json_serialize_handlers(desc); + msgdef_json_serialize_handlers(desc, RTEST(preserve_proto_fieldnames)); upb_json_printer* printer; stackenv se; VALUE ret; diff --git a/ruby/ext/google/protobuf_c/message.c b/ruby/ext/google/protobuf_c/message.c index 283939c9..e16250f3 100644 --- a/ruby/ext/google/protobuf_c/message.c +++ b/ruby/ext/google/protobuf_c/message.c @@ -151,32 +151,30 @@ VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) { name_len--; } - // Check for a oneof name first. - o = upb_msgdef_ntoo(self->descriptor->msgdef, - name, name_len); + // 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 (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); - } - - // Otherwise, check for a field with that name. - f = upb_msgdef_ntof(self->descriptor->msgdef, - name, name_len); - - if (f == NULL) { - return rb_call_super(argc, argv); - } - - 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); + // 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); + } } } @@ -475,7 +473,7 @@ VALUE build_class_from_descriptor(Descriptor* desc) { 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, "encode_json", Message_encode_json, 1); + rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1); rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0); return klass; diff --git a/ruby/ext/google/protobuf_c/protobuf.h b/ruby/ext/google/protobuf_c/protobuf.h index 21ce7bb3..2834c894 100644 --- a/ruby/ext/google/protobuf_c/protobuf.h +++ b/ruby/ext/google/protobuf_c/protobuf.h @@ -115,6 +115,7 @@ struct Descriptor { 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. @@ -498,7 +499,7 @@ 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(VALUE klass, VALUE msg_rb); +VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass); VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj); diff --git a/ruby/ext/google/protobuf_c/upb.c b/ruby/ext/google/protobuf_c/upb.c index b2a69b66..74a2a1db 100644 --- a/ruby/ext/google/protobuf_c/upb.c +++ b/ruby/ext/google/protobuf_c/upb.c @@ -12,7 +12,7 @@ typedef struct { } str_t; static str_t *newstr(const char *data, size_t len) { - str_t *ret = malloc(sizeof(*ret) + len); + str_t *ret = upb_gmalloc(sizeof(*ret) + len); if (!ret) return NULL; ret->len = len; memcpy(ret->str, data, len); @@ -20,7 +20,7 @@ static str_t *newstr(const char *data, size_t len) { return ret; } -static void freestr(str_t *s) { free(s); } +static void freestr(str_t *s) { upb_gfree(s); } /* isalpha() etc. from <ctype.h> are locale-dependent, which we don't want. */ static bool upb_isbetween(char c, char low, char high) { @@ -65,6 +65,22 @@ static bool upb_isident(const char *str, size_t len, bool full, upb_status *s) { 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 ********************************************************************/ @@ -72,14 +88,39 @@ 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) { assert(!upb_def_isfrozen(def)); - if (!upb_isident(fullname, strlen(fullname), true, s)) return false; - free((void*)def->fullname); - def->fullname = upb_strdup(fullname); + 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; } + upb_def *upb_def_dup(const upb_def *def, const void *o) { switch (def->type) { case UPB_DEF_MSG: @@ -102,11 +143,12 @@ static bool upb_def_init(upb_def *def, upb_deftype_t type, def->type = type; def->fullname = NULL; def->came_from_user = false; + def->file = NULL; return true; } static void upb_def_uninit(upb_def *def) { - free((void*)def->fullname); + upb_gfree((void*)def->fullname); } static const char *msgdef_name(const upb_msgdef *m) { @@ -243,8 +285,19 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { int i; uint32_t selector; int n = upb_msgdef_numfields(m); - upb_fielddef **fields = malloc(n * sizeof(*fields)); - if (!fields) return false; + 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); @@ -253,7 +306,7 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { upb_fielddef *f = upb_msg_iter_field(&j); assert(f->msg.def == m); if (!upb_validate_field(f, s)) { - free(fields); + upb_gfree(fields); return false; } if (upb_fielddef_issubmsg(f)) { @@ -313,15 +366,12 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { #undef TRY #endif - free(fields); + upb_gfree(fields); return true; } -bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) { - int i; - int maxdepth; - bool ret; - upb_status_clear(s); +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. */ @@ -347,8 +397,9 @@ bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) { /* Second pass of validation. Also assign selector bases and indexes, and * compact tables. */ for (i = 0; i < n; i++) { - upb_msgdef *m = upb_dyncast_msgdef_mutable(defs[i]); - upb_enumdef *e = upb_dyncast_enumdef_mutable(defs[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)) { @@ -359,23 +410,31 @@ bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) { } } - /* Def graph contains FieldDefs between each MessageDef, so double the - * limit. */ - maxdepth = UPB_MAX_MESSAGE_DEPTH * 2; - - /* Validation all passed; freeze the defs. */ - ret = upb_refcounted_freeze((upb_refcounted * const *)defs, n, s, maxdepth); - assert(!(s && ret != upb_ok(s))); - return ret; + return true; err: for (i = 0; i < n; i++) { - defs[i]->came_from_user = false; + upb_def *def = defs[i]; + def->came_from_user = false; } 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 ****************************************************************/ @@ -384,21 +443,26 @@ static void upb_enumdef_free(upb_refcounted *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_strdup() from upb_enumdef_addval(). */ - free(upb_value_getcstr(upb_inttable_iter_value(&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)); - free(e); + upb_gfree(e); } +const struct upb_refcounted_vtbl upb_enumdef_vtbl = {NULL, &upb_enumdef_free}; + upb_enumdef *upb_enumdef_new(const void *owner) { - static const struct upb_refcounted_vtbl vtbl = {NULL, &upb_enumdef_free}; - upb_enumdef *e = malloc(sizeof(*e)); + upb_enumdef *e = upb_gmalloc(sizeof(*e)); if (!e) return NULL; - if (!upb_def_init(upb_enumdef_upcast_mutable(e), UPB_DEF_ENUM, &vtbl, owner)) + + 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; @@ -406,7 +470,7 @@ upb_enumdef *upb_enumdef_new(const void *owner) { err1: upb_strtable_uninit(&e->ntoi); err2: - free(e); + upb_gfree(e); return NULL; } @@ -434,6 +498,10 @@ 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); @@ -441,27 +509,36 @@ bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname, 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) && - !upb_inttable_insert(&e->iton, num, upb_value_cstr(upb_strdup(name)))) { - upb_status_seterrmsg(status, "out of memory"); - upb_strtable_remove(&e->ntoi, name, NULL); - 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_VAR(ok, ok); } + return true; } @@ -537,7 +614,7 @@ static void visitfield(const upb_refcounted *r, upb_refcounted_visit *visit, visit(r, upb_msgdef_upcast2(upb_fielddef_containingtype(f)), closure); } if (upb_fielddef_containingoneof(f)) { - visit(r, upb_oneofdef_upcast2(upb_fielddef_containingoneof(f)), closure); + 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); @@ -548,9 +625,9 @@ static void freefield(upb_refcounted *r) { upb_fielddef *f = (upb_fielddef*)r; upb_fielddef_uninit_default(f); if (f->subdef_is_symbolic) - free(f->sub.name); + upb_gfree(f->sub.name); upb_def_uninit(upb_fielddef_upcast_mutable(f)); - free(f); + upb_gfree(f); } static const char *enumdefaultstr(const upb_fielddef *f) { @@ -606,12 +683,14 @@ static bool enumdefaultint32(const upb_fielddef *f, int32_t *val) { return false; } +const struct upb_refcounted_vtbl upb_fielddef_vtbl = {visitfield, freefield}; + upb_fielddef *upb_fielddef_new(const void *o) { - static const struct upb_refcounted_vtbl vtbl = {visitfield, freefield}; - upb_fielddef *f = malloc(sizeof(*f)); + upb_fielddef *f = upb_gmalloc(sizeof(*f)); if (!f) return NULL; - if (!upb_def_init(upb_fielddef_upcast_mutable(f), UPB_DEF_FIELD, &vtbl, o)) { - free(f); + 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; @@ -662,7 +741,7 @@ upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) { srcname = f->sub.def ? upb_def_fullname(f->sub.def) : NULL; } if (srcname) { - char *newname = malloc(strlen(f->sub.def->fullname) + 2); + char *newname = upb_gmalloc(strlen(f->sub.def->fullname) + 2); if (!newname) { upb_fielddef_unref(newf, owner); return NULL; @@ -670,7 +749,7 @@ upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) { strcpy(newname, "."); strcat(newname, f->sub.def->fullname); upb_fielddef_setsubdefname(newf, newname, NULL); - free(newname); + upb_gfree(newname); } return newf; @@ -777,11 +856,12 @@ const char *upb_fielddef_containingtypename(upb_fielddef *f) { } static void release_containingtype(upb_fielddef *f) { - if (f->msg_is_symbolic) free(f->msg.name); + 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; assert(!upb_fielddef_isfrozen(f)); if (upb_fielddef_containingtype(f)) { upb_status_seterrmsg(s, "field has already been added to a message."); @@ -789,8 +869,15 @@ bool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name, } /* 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 = upb_strdup(name); + f->msg.name = name_copy; f->msg_is_symbolic = true; return true; } @@ -1191,7 +1278,7 @@ static bool upb_subdef_typecheck(upb_fielddef *f, const upb_def *subdef, static void release_subdef(upb_fielddef *f) { if (f->subdef_is_symbolic) { - free(f->sub.name); + upb_gfree(f->sub.name); } else if (f->sub.def) { upb_unref2(f->sub.def, f); } @@ -1221,15 +1308,23 @@ bool upb_fielddef_setenumsubdef(upb_fielddef *f, const upb_enumdef *subdef, bool upb_fielddef_setsubdefname(upb_fielddef *f, const char *name, upb_status *s) { + char *name_copy; 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 = upb_strdup(name); + f->sub.name = name_copy; f->subdef_is_symbolic = true; return true; } @@ -1263,7 +1358,7 @@ bool upb_fielddef_haspresence(const upb_fielddef *f) { /* 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->primitives_have_presence; + return f->msg.def->syntax == UPB_SYNTAX_PROTO2; } bool upb_fielddef_hassubdef(const upb_fielddef *f) { @@ -1299,38 +1394,39 @@ static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit, !upb_msg_oneof_done(&o); upb_msg_oneof_next(&o)) { upb_oneofdef *f = upb_msg_iter_oneof(&o); - visit(r, upb_oneofdef_upcast2(f), closure); + visit(r, upb_oneofdef_upcast(f), closure); } } static void freemsg(upb_refcounted *r) { upb_msgdef *m = (upb_msgdef*)r; - upb_strtable_uninit(&m->ntoo); upb_strtable_uninit(&m->ntof); upb_inttable_uninit(&m->itof); upb_def_uninit(upb_msgdef_upcast_mutable(m)); - free(m); + upb_gfree(m); } +const struct upb_refcounted_vtbl upb_msgdef_vtbl = {visitmsg, freemsg}; + upb_msgdef *upb_msgdef_new(const void *owner) { - static const struct upb_refcounted_vtbl vtbl = {visitmsg, freemsg}; - upb_msgdef *m = malloc(sizeof(*m)); + upb_msgdef *m = upb_gmalloc(sizeof(*m)); if (!m) return NULL; - if (!upb_def_init(upb_msgdef_upcast_mutable(m), UPB_DEF_MSG, &vtbl, owner)) + + 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 err3; - if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err2; - if (!upb_strtable_init(&m->ntoo, UPB_CTYPE_PTR)) goto err1; + } + + 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->primitives_have_presence = true; + m->syntax = UPB_SYNTAX_PROTO2; return m; err1: - upb_strtable_uninit(&m->ntof); -err2: upb_inttable_uninit(&m->itof); -err3: - free(m); +err2: + upb_gfree(m); return NULL; } @@ -1345,7 +1441,7 @@ upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner) { upb_def_fullname(upb_msgdef_upcast(m)), NULL); newm->map_entry = m->map_entry; - newm->primitives_have_presence = m->primitives_have_presence; + newm->syntax = m->syntax; UPB_ASSERT_VAR(ok, ok); for(upb_msg_field_begin(&i, m); !upb_msg_field_done(&i); @@ -1379,11 +1475,28 @@ 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, @@ -1394,9 +1507,11 @@ static bool check_field_add(const upb_msgdef *m, const upb_fielddef *f, } 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_ntofz(m, upb_fielddef_name(f)) || - upb_msgdef_itof(m, upb_fielddef_number(f))) { - upb_status_seterrmsg(s, "duplicate field name or number for field"); + } 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; @@ -1457,8 +1572,8 @@ bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor, } else if (upb_oneofdef_name(o) == NULL) { upb_status_seterrmsg(s, "oneofdef name was not set"); return false; - } else if (upb_msgdef_ntooz(m, upb_oneofdef_name(o))) { - upb_status_seterrmsg(s, "duplicate oneof name"); + } 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; } @@ -1475,7 +1590,7 @@ bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor, /* Add oneof itself first. */ o->parent = m; - upb_strtable_insert(&m->ntoo, upb_oneofdef_name(o), upb_value_ptr(o)); + upb_strtable_insert(&m->ntof, upb_oneofdef_name(o), upb_value_ptr(o)); upb_ref2(o, m); upb_ref2(m, o); @@ -1490,11 +1605,6 @@ bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor, return true; } -void upb_msgdef_setprimitiveshavepresence(upb_msgdef *m, bool have_presence) { - assert(!upb_msgdef_isfrozen(m)); - m->primitives_have_presence = have_presence; -} - const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) { upb_value val; return upb_inttable_lookup32(&m->itof, i, &val) ? @@ -1504,23 +1614,47 @@ 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) { upb_value val; - return upb_strtable_lookup2(&m->ntof, name, len, &val) ? - upb_value_getptr(val) : NULL; + + 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; - return upb_strtable_lookup2(&m->ntoo, name, len, &val) ? - upb_value_getptr(val) : NULL; + + 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)); + assert((*o != NULL) ^ (*f != NULL)); /* Exactly one of the two should be set. */ + return true; } int upb_msgdef_numfields(const upb_msgdef *m) { - return upb_strtable_count(&m->ntof); + /* The number table contains only fields. */ + return upb_inttable_count(&m->itof); } int upb_msgdef_numoneofs(const upb_msgdef *m) { - return upb_strtable_count(&m->ntoo); + /* 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) { @@ -1551,10 +1685,21 @@ void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) { } void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) { - upb_strtable_begin(iter, &m->ntoo); + 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) { 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); @@ -1587,26 +1732,36 @@ static void freeoneof(upb_refcounted *r) { upb_oneofdef *o = (upb_oneofdef*)r; upb_strtable_uninit(&o->ntof); upb_inttable_uninit(&o->itof); - upb_def_uninit(upb_oneofdef_upcast_mutable(o)); - free(o); + 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) { - static const struct upb_refcounted_vtbl vtbl = {visitoneof, freeoneof}; - upb_oneofdef *o = malloc(sizeof(*o)); + upb_oneofdef *o = upb_gmalloc(sizeof(*o)); + + if (!o) { + return NULL; + } + o->parent = NULL; - if (!o) return NULL; - if (!upb_def_init(upb_oneofdef_upcast_mutable(o), UPB_DEF_ONEOF, &vtbl, - owner)) + 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: - free(o); + upb_gfree(o); return NULL; } @@ -1615,8 +1770,7 @@ upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner) { upb_oneof_iter i; upb_oneofdef *newo = upb_oneofdef_new(owner); if (!newo) return NULL; - ok = upb_def_setfullname(upb_oneofdef_upcast_mutable(newo), - upb_def_fullname(upb_oneofdef_upcast(o)), NULL); + ok = upb_oneofdef_setname(newo, upb_oneofdef_name(o), NULL); UPB_ASSERT_VAR(ok, ok); for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) { upb_fielddef *f = upb_fielddef_dup(upb_oneof_iter_field(&i), &f); @@ -1628,17 +1782,28 @@ upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner) { return newo; } -const char *upb_oneofdef_name(const upb_oneofdef *o) { - return upb_def_fullname(upb_oneofdef_upcast(o)); -} +const char *upb_oneofdef_name(const upb_oneofdef *o) { return o->name; } -bool upb_oneofdef_setname(upb_oneofdef *o, const char *fullname, - upb_status *s) { +bool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s) { + assert(!upb_oneofdef_isfrozen(o)); if (upb_oneofdef_containingtype(o)) { upb_status_seterrmsg(s, "oneof already added to a message"); return false; } - return upb_def_setfullname(upb_oneofdef_upcast_mutable(o), fullname, s); + + 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) { @@ -1757,276 +1922,191 @@ void upb_oneof_iter_setdone(upb_oneof_iter *iter) { upb_inttable_iter_setdone(iter); } +/* upb_filedef ****************************************************************/ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -typedef struct cleanup_ent { - upb_cleanup_func *cleanup; - void *ud; - struct cleanup_ent *next; -} cleanup_ent; - -static void *seeded_alloc(void *ud, void *ptr, size_t oldsize, size_t size); - -/* Default allocator **********************************************************/ - -/* Just use realloc, keeping all allocated blocks in a linked list to destroy at - * the end. */ - -typedef struct mem_block { - /* List is doubly-linked, because in cases where realloc() moves an existing - * block, we need to be able to remove the old pointer from the list - * efficiently. */ - struct mem_block *prev, *next; -#ifndef NDEBUG - size_t size; /* Doesn't include mem_block structure. */ -#endif -} mem_block; - -typedef struct { - mem_block *head; -} default_alloc_ud; - -static void *default_alloc(void *_ud, void *ptr, size_t oldsize, size_t size) { - default_alloc_ud *ud = _ud; - mem_block *from, *block; - void *ret; - UPB_UNUSED(oldsize); - - from = ptr ? (void*)((char*)ptr - sizeof(mem_block)) : NULL; - -#ifndef NDEBUG - if (from) { - assert(oldsize <= from->size); - } -#endif - - /* TODO(haberman): we probably need to provide even better alignment here, - * like 16-byte alignment of the returned data pointer. */ - block = realloc(from, size + sizeof(mem_block)); - if (!block) return NULL; - ret = (char*)block + sizeof(*block); - -#ifndef NDEBUG - block->size = size; -#endif +static void visitfiledef(const upb_refcounted *r, upb_refcounted_visit *visit, + void *closure) { + const upb_filedef *f = (const upb_filedef*)r; + size_t i; - if (from) { - if (block != from) { - /* The block was moved, so pointers in next and prev blocks must be - * updated to its new location. */ - if (block->next) block->next->prev = block; - if (block->prev) block->prev->next = block; - if (ud->head == from) ud->head = block; - } - } else { - /* Insert at head of linked list. */ - block->prev = NULL; - block->next = ud->head; - if (block->next) block->next->prev = block; - ud->head = block; + for(i = 0; i < upb_filedef_defcount(f); i++) { + visit(r, upb_def_upcast(upb_filedef_def(f, i)), closure); } - - return ret; } -static void default_alloc_cleanup(void *_ud) { - default_alloc_ud *ud = _ud; - mem_block *block = ud->head; +static void freefiledef(upb_refcounted *r) { + upb_filedef *f = (upb_filedef*)r; + size_t i; - while (block) { - void *to_free = block; - block = block->next; - free(to_free); + 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); +} -/* Standard error functions ***************************************************/ +const struct upb_refcounted_vtbl upb_filedef_vtbl = {visitfiledef, freefiledef}; -static bool default_err(void *ud, const upb_status *status) { - UPB_UNUSED(ud); - UPB_UNUSED(status); - return false; -} +upb_filedef *upb_filedef_new(const void *owner) { + upb_filedef *f = upb_gmalloc(sizeof(*f)); -static bool write_err_to(void *ud, const upb_status *status) { - upb_status *copy_to = ud; - upb_status_copy(copy_to, status); - return false; -} + if (!f) { + return NULL; + } + f->package = NULL; + f->name = NULL; + f->syntax = UPB_SYNTAX_PROTO2; -/* upb_env ********************************************************************/ + if (!upb_refcounted_init(upb_filedef_upcast_mutable(f), &upb_filedef_vtbl, + owner)) { + goto err; + } -void upb_env_init(upb_env *e) { - default_alloc_ud *ud = (default_alloc_ud*)&e->default_alloc_ud; - e->ok_ = true; - e->bytes_allocated = 0; - e->cleanup_head = NULL; + if (!upb_inttable_init(&f->defs, UPB_CTYPE_CONSTPTR)) { + goto err; + } - ud->head = NULL; + if (!upb_inttable_init(&f->deps, UPB_CTYPE_CONSTPTR)) { + goto err2; + } - /* Set default functions. */ - upb_env_setallocfunc(e, default_alloc, ud); - upb_env_seterrorfunc(e, default_err, NULL); -} + return f; -void upb_env_uninit(upb_env *e) { - cleanup_ent *ent = e->cleanup_head; - while (ent) { - ent->cleanup(ent->ud); - ent = ent->next; - } +err2: + upb_inttable_uninit(&f->defs); - /* Must do this after running cleanup functions, because this will delete - the memory we store our cleanup entries in! */ - if (e->alloc == default_alloc) { - default_alloc_cleanup(e->alloc_ud); - } +err: + upb_gfree(f); + return NULL; } -UPB_FORCEINLINE void upb_env_setallocfunc(upb_env *e, upb_alloc_func *alloc, - void *ud) { - e->alloc = alloc; - e->alloc_ud = ud; +const char *upb_filedef_name(const upb_filedef *f) { + return f->name; } -UPB_FORCEINLINE void upb_env_seterrorfunc(upb_env *e, upb_error_func *func, - void *ud) { - e->err = func; - e->err_ud = ud; +const char *upb_filedef_package(const upb_filedef *f) { + return f->package; } -void upb_env_reporterrorsto(upb_env *e, upb_status *status) { - e->err = write_err_to; - e->err_ud = status; +upb_syntax_t upb_filedef_syntax(const upb_filedef *f) { + return f->syntax; } -bool upb_env_ok(const upb_env *e) { - return e->ok_; +size_t upb_filedef_defcount(const upb_filedef *f) { + return upb_inttable_count(&f->defs); } -bool upb_env_reporterror(upb_env *e, const upb_status *status) { - e->ok_ = false; - return e->err(e->err_ud, status); +size_t upb_filedef_depcount(const upb_filedef *f) { + return upb_inttable_count(&f->deps); } -bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud) { - cleanup_ent *ent = upb_env_malloc(e, sizeof(cleanup_ent)); - if (!ent) return false; - - ent->cleanup = func; - ent->ud = ud; - ent->next = e->cleanup_head; - e->cleanup_head = ent; - - return true; -} +const upb_def *upb_filedef_def(const upb_filedef *f, size_t i) { + upb_value v; -void *upb_env_malloc(upb_env *e, size_t size) { - e->bytes_allocated += size; - if (e->alloc == seeded_alloc) { - /* This is equivalent to the next branch, but allows inlining for a - * measurable perf benefit. */ - return seeded_alloc(e->alloc_ud, NULL, 0, size); + if (upb_inttable_lookup32(&f->defs, i, &v)) { + return upb_value_getconstptr(v); } else { - return e->alloc(e->alloc_ud, NULL, 0, size); + return NULL; } } -void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size) { - char *ret; - assert(oldsize <= size); - ret = e->alloc(e->alloc_ud, ptr, oldsize, size); - -#ifndef NDEBUG - /* Overwrite non-preserved memory to ensure callers are passing the oldsize - * that they truly require. */ - memset(ret + oldsize, 0xff, size - oldsize); -#endif +const upb_filedef *upb_filedef_dep(const upb_filedef *f, size_t i) { + upb_value v; - return ret; + if (upb_inttable_lookup32(&f->deps, i, &v)) { + return upb_value_getconstptr(v); + } else { + return NULL; + } } -size_t upb_env_bytesallocated(const upb_env *e) { - return e->bytes_allocated; +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; } - -/* upb_seededalloc ************************************************************/ - -/* Be conservative and choose 16 in case anyone is using SSE. */ -static const size_t maxalign = 16; - -static size_t align_up(size_t size) { - return ((size + maxalign - 1) / maxalign) * maxalign; +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; } -UPB_FORCEINLINE static void *seeded_alloc(void *ud, void *ptr, size_t oldsize, - size_t size) { - upb_seededalloc *a = ud; - - size = align_up(size); - - assert(a->mem_limit >= a->mem_ptr); +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; - if (oldsize == 0 && size <= (size_t)(a->mem_limit - a->mem_ptr)) { - /* Fast path: we can satisfy from the initial allocation. */ - void *ret = a->mem_ptr; - a->mem_ptr += size; - return ret; - } else { - char *chptr = ptr; - /* Slow path: fallback to other allocator. */ - a->need_cleanup = true; - /* Is `ptr` part of the user-provided initial block? Don't pass it to the - * default allocator if so; otherwise, it may try to realloc() the block. */ - if (chptr >= a->mem_base && chptr < a->mem_limit) { - void *ret; - assert(chptr + oldsize <= a->mem_limit); - ret = a->alloc(a->alloc_ud, NULL, 0, size); - if (ret) memcpy(ret, ptr, oldsize); - return ret; - } else { - return a->alloc(a->alloc_ud, ptr, oldsize, size); + { + /* 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; + } } } -} - -void upb_seededalloc_init(upb_seededalloc *a, void *mem, size_t len) { - default_alloc_ud *ud = (default_alloc_ud*)&a->default_alloc_ud; - a->mem_base = mem; - a->mem_ptr = mem; - a->mem_limit = (char*)mem + len; - a->need_cleanup = false; - a->returned_allocfunc = false; - ud->head = NULL; - - upb_seededalloc_setfallbackalloc(a, default_alloc, ud); + return true; } -void upb_seededalloc_uninit(upb_seededalloc *a) { - if (a->alloc == default_alloc && a->need_cleanup) { - default_alloc_cleanup(a->alloc_ud); +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; } -} -UPB_FORCEINLINE void upb_seededalloc_setfallbackalloc(upb_seededalloc *a, - upb_alloc_func *alloc, - void *ud) { - assert(!a->returned_allocfunc); - a->alloc = alloc; - a->alloc_ud = ud; + if (upb_inttable_push(&f->defs, upb_value_constptr(def))) { + def->file = f; + upb_ref2(def, f); + 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; + } } -upb_alloc_func *upb_seededalloc_getallocfunc(upb_seededalloc *a) { - a->returned_allocfunc = true; - return seeded_alloc; +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; + } } /* ** TODO(haberman): it's unclear whether a lot of the consistency checks should @@ -2034,10 +2114,16 @@ upb_alloc_func *upb_seededalloc_getallocfunc(upb_seededalloc *a) { */ -#include <stdlib.h> #include <string.h> +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. */ @@ -2057,8 +2143,8 @@ static void freehandlers(upb_refcounted *r) { upb_inttable_uninit(&h->cleanup_); upb_msgdef_unref(h->msg, h); - free(h->sub); - free(h); + upb_gfree(h->sub); + upb_gfree(h); } static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit, @@ -2308,14 +2394,20 @@ upb_handlers *upb_handlers_new(const upb_msgdef *md, const void *owner) { assert(upb_msgdef_isfrozen(md)); extra = sizeof(upb_handlers_tabent) * (md->selector_count - 1); - h = calloc(sizeof(*h) + extra, 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_); - h->sub = calloc(md->submsg_field_count, sizeof(*h->sub)); - if (!h->sub) goto oom; + + 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; @@ -2730,7 +2822,6 @@ bool upb_byteshandler_setendstr(upb_byteshandler *h, #include <setjmp.h> -#include <stdlib.h> static void freeobj(upb_refcounted *o); @@ -2806,8 +2897,31 @@ void upb_unlock(); /* 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 immediately fail. */ -#define CHECK_OOM(predicate) if (!(predicate)) { assert(predicate); exit(1); } + * 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 <stdlib.h> + +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). */ @@ -2815,8 +2929,7 @@ typedef struct { } trackedref; static trackedref *trackedref_new(bool is_ref2) { - trackedref *ret = malloc(sizeof(*ret)); - CHECK_OOM(ret); + trackedref *ret = upb_malloc(&upb_alloc_debugrefs, sizeof(*ret)); ret->count = 1; ret->is_ref2 = is_ref2; return ret; @@ -2841,15 +2954,15 @@ static void track(const upb_refcounted *r, const void *owner, bool ref2) { ref->count++; } else { trackedref *ref = trackedref_new(ref2); - bool ok = upb_inttable_insertptr(r->refs, owner, upb_value_ptr(ref)); - CHECK_OOM(ok); + 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; assert(!upb_inttable_lookupptr(from->ref2s, r, NULL)); - ok = upb_inttable_insertptr(from->ref2s, r, upb_value_ptr(NULL)); - CHECK_OOM(ok); + upb_inttable_insertptr2(from->ref2s, r, upb_value_ptr(NULL), + &upb_alloc_debugrefs); } } upb_unlock(); @@ -2907,7 +3020,6 @@ static void getref2s(const upb_refcounted *owner, upb_inttable *tab) { upb_value v; upb_value count; trackedref *ref; - bool ok; bool found; upb_refcounted *to = (upb_refcounted*)upb_inttable_iter_key(&i); @@ -2918,8 +3030,7 @@ static void getref2s(const upb_refcounted *owner, upb_inttable *tab) { ref = upb_value_getptr(v); count = upb_value_int32(ref->count); - ok = upb_inttable_insertptr(tab, to, count); - CHECK_OOM(ok); + upb_inttable_insertptr2(tab, to, count, &upb_alloc_debugrefs); } upb_unlock(); } @@ -2945,21 +3056,19 @@ static void visit_check(const upb_refcounted *obj, const upb_refcounted *subobj, assert(removed); newcount = upb_value_getint32(v) - 1; if (newcount > 0) { - upb_inttable_insert(ref2, (uintptr_t)subobj, upb_value_int32(newcount)); + 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) { - bool ok; - /* 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; - ok = upb_inttable_init(&state.ref2, UPB_CTYPE_INT32); - CHECK_OOM(ok); + upb_inttable_init2(&state.ref2, UPB_CTYPE_INT32, &upb_alloc_debugrefs); getref2s(r, &state.ref2); /* This should visit any children in the ref2 table. */ @@ -2967,32 +3076,22 @@ static void visit(const upb_refcounted *r, upb_refcounted_visit *v, /* This assertion will fail if the visit() function missed any children. */ assert(upb_inttable_count(&state.ref2) == 0); - upb_inttable_uninit(&state.ref2); + upb_inttable_uninit2(&state.ref2, &upb_alloc_debugrefs); if (r->vtbl->visit) r->vtbl->visit(r, v, closure); } -static bool trackinit(upb_refcounted *r) { - r->refs = malloc(sizeof(*r->refs)); - r->ref2s = malloc(sizeof(*r->ref2s)); - if (!r->refs || !r->ref2s) goto err1; - - if (!upb_inttable_init(r->refs, UPB_CTYPE_PTR)) goto err1; - if (!upb_inttable_init(r->ref2s, UPB_CTYPE_PTR)) goto err2; - return true; - -err2: - upb_inttable_uninit(r->refs); -err1: - free(r->refs); - free(r->ref2s); - return false; +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_uninit(r->refs); - upb_inttable_uninit(r->ref2s); - free(r->refs); - free(r->ref2s); + 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 @@ -3015,9 +3114,8 @@ static void checkref(const upb_refcounted *r, const void *owner, bool ref2) { UPB_UNUSED(ref2); } -static bool trackinit(upb_refcounted *r) { +static void trackinit(upb_refcounted *r) { UPB_UNUSED(r); - return true; } static void trackfree(const upb_refcounted *r) { @@ -3127,12 +3225,12 @@ static upb_refcounted *pop(tarjan *t) { } static void tarjan_newgroup(tarjan *t) { - uint32_t *group = malloc(sizeof(*group)); + 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))) { - free(group); + upb_gfree(group); oom(t); } *group = 0; @@ -3307,7 +3405,7 @@ static bool freeze(upb_refcounted *const*roots, int n, upb_status *s, if (obj == move) { /* Removing the last object from a group. */ assert(*obj->group == obj->individual_count); - free(obj->group); + upb_gfree(obj->group); } else { obj->next = move->next; /* This may decrease to zero; we'll collect GRAY objects (if any) that @@ -3363,7 +3461,7 @@ static bool freeze(upb_refcounted *const*roots, int n, upb_status *s, /* 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). */ - free(obj->group); + 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()). */ @@ -3383,7 +3481,7 @@ err4: if (!ret) { upb_inttable_begin(&iter, &t.groups); for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) - free(upb_value_getptr(upb_inttable_iter_value(&iter))); + upb_gfree(upb_value_getptr(upb_inttable_iter_value(&iter))); } upb_inttable_uninit(&t.groups); err3: @@ -3407,7 +3505,7 @@ static void merge(upb_refcounted *r, upb_refcounted *from) { if (merged(r, from)) return; *r->group += *from->group; - free(from->group); + upb_gfree(from->group); base = from; /* Set all refcount pointers in the "from" chain to the merged refcount. @@ -3441,7 +3539,7 @@ static void unref(const upb_refcounted *r) { if (unrefgroup(r->group)) { const upb_refcounted *o; - free(r->group); + upb_gfree(r->group); /* In two passes, since release_ref2 needs a guarantee that any subobjs * are alive. */ @@ -3485,13 +3583,10 @@ bool upb_refcounted_init(upb_refcounted *r, r->vtbl = vtbl; r->individual_count = 0; r->is_frozen = false; - r->group = malloc(sizeof(*r->group)); + r->group = upb_gmalloc(sizeof(*r->group)); if (!r->group) return false; *r->group = 0; - if (!trackinit(r)) { - free(r->group); - return false; - } + trackinit(r); upb_refcounted_ref(r, owner); return true; } @@ -3550,15 +3645,16 @@ void upb_refcounted_checkref(const upb_refcounted *r, const void *owner) { 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++) { assert(!roots[i]->is_frozen); } - return freeze(roots, n, s, maxdepth); + ret = freeze(roots, n, s, maxdepth); + assert(!s || ret == upb_ok(s)); + return ret; } -#include <stdlib.h> - /* Fallback implementation if the shim is not specialized by the JIT. */ #define SHIM_WRITER(type, ctype) \ bool upb_shim_set ## type (void *c, const void *hd, ctype val) { \ @@ -3584,14 +3680,14 @@ bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset, upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; bool ok; - upb_shim_data *d = malloc(sizeof(*d)); + upb_shim_data *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, free); + upb_handlers_addcleanup(h, d, upb_gfree); #define TYPE(u, l) \ case UPB_TYPE_##u: \ @@ -3642,7 +3738,6 @@ const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s, } -#include <stdlib.h> #include <string.h> static void upb_symtab_free(upb_refcounted *r) { @@ -3654,13 +3749,17 @@ static void upb_symtab_free(upb_refcounted *r) { upb_def_unref(def, s); } upb_strtable_uninit(&s->symtab); - free(s); + upb_gfree(s); } - upb_symtab *upb_symtab_new(const void *owner) { static const struct upb_refcounted_vtbl vtbl = {NULL, &upb_symtab_free}; - upb_symtab *s = malloc(sizeof(*s)); + + upb_symtab *s = upb_gmalloc(sizeof(*s)); + if (!s) { + return NULL; + } + upb_refcounted_init(upb_symtab_upcast_mutable(s), &vtbl, owner); upb_strtable_init(&s->symtab, UPB_CTYPE_PTR); return s; @@ -3834,14 +3933,23 @@ oom: /* TODO(haberman): we need a lot more testing of error conditions. * The came_from_user stuff in particular is not tested. */ -bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, - upb_status *status) { - int i; +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; upb_inttable seen; + if (n == 0 && !freeze_also) { + return true; + } + assert(!upb_symtab_isfrozen(s)); if (!upb_strtable_init(&addtab, UPB_CTYPE_PTR)) { upb_status_seterrmsg(status, "out of memory"); @@ -3983,15 +4091,38 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, } } - /* We need an array of the defs in addtab, for passing to upb_def_freeze. */ - add_defs = malloc(sizeof(void*) * upb_strtable_count(&addtab)); + /* 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 (n = 0; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { - add_defs[n++] = upb_value_getptr(upb_strtable_iter_value(&iter)); + for (add_n = 0; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { + add_defs[add_n++] = upb_value_getptr(upb_strtable_iter_value(&iter)); } - if (!upb_def_freeze(add_defs, n, status)) goto err; + /* 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. */ @@ -3999,8 +4130,8 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, /* TODO(haberman) we don't properly handle errors after this point (like * OOM in upb_strtable_insert() below). */ - for (i = 0; i < n; i++) { - upb_def *def = add_defs[i]; + for (i = 0; i < add_n; i++) { + upb_def *def = (upb_def*)add_objs[i]; const char *name = upb_def_fullname(def); upb_value v; bool success; @@ -4012,7 +4143,7 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, success = upb_strtable_insert(&s->symtab, name, upb_value_ptr(def)); UPB_ASSERT_VAR(success, success == true); } - free(add_defs); + upb_gfree(add_defs); return true; oom_err: @@ -4033,11 +4164,40 @@ err: { } } upb_strtable_uninit(&addtab); - free(add_defs); + upb_gfree(add_defs); 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) { @@ -4076,7 +4236,6 @@ const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter) { */ -#include <stdlib.h> #include <string.h> #define UPB_MAXARRSIZE 16 /* 64k. */ @@ -4085,6 +4244,17 @@ const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter) { #define ARRAY_SIZE(x) \ ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) +#ifdef NDEBUG +static void upb_check_alloc(upb_table *t, upb_alloc *a) { + UPB_UNUSED(t); + UPB_UNUSED(a); +} +#else +static void upb_check_alloc(upb_table *t, upb_alloc *a) { + assert(t->alloc == a); +} +#endif + static const double MAX_LOAD = 0.85; /* The minimum utilization of the array part of a mixed hash/array table. This @@ -4102,11 +4272,11 @@ int log2ceil(uint64_t v) { return UPB_MIN(UPB_MAXARRSIZE, ret); } -char *upb_strdup(const char *s) { - return upb_strdup2(s, strlen(s)); +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) { +char *upb_strdup2(const char *s, size_t len, upb_alloc *a) { size_t n; char *p; @@ -4115,7 +4285,7 @@ char *upb_strdup2(const char *s, size_t len) { /* 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 = malloc(n); + p = upb_malloc(a, n); if (p) { memcpy(p, s, len); p[len] = 0; @@ -4163,16 +4333,20 @@ static bool isfull(upb_table *t) { } } -static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2) { +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 = malloc(bytes); + t->entries = upb_malloc(a, bytes); if (!t->entries) return false; memset(mutable_entries(t), 0, bytes); } else { @@ -4181,7 +4355,10 @@ static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2) { return true; } -static void uninit(upb_table *t) { free(mutable_entries(t)); } +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); @@ -4334,8 +4511,8 @@ static size_t begin(const upb_table *t) { /* A simple "subclass" of upb_table that only adds a hash function for strings. */ -static upb_tabkey strcopy(lookupkey_t k2) { - char *str = malloc(k2.str.len + sizeof(uint32_t) + 1); +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); @@ -4354,51 +4531,56 @@ static bool streql(upb_tabkey k1, lookupkey_t k2) { return len == k2.str.len && memcmp(str, k2.str.str, len) == 0; } -bool upb_strtable_init(upb_strtable *t, upb_ctype_t ctype) { - return init(&t->t, ctype, 2); +bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, upb_alloc *a) { + return init(&t->t, ctype, 2, a); } -void upb_strtable_uninit(upb_strtable *t) { +void upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) { size_t i; for (i = 0; i < upb_table_size(&t->t); i++) - free((void*)t->t.entries[i].key); - uninit(&t->t); + upb_free(a, (void*)t->t.entries[i].key); + uninit(&t->t, a); } -bool upb_strtable_resize(upb_strtable *t, size_t size_lg2) { +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, t->t.ctype, size_lg2)) + 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_insert2( + upb_strtable_insert3( &new_table, upb_strtable_iter_key(&i), upb_strtable_iter_keylength(&i), - upb_strtable_iter_value(&i)); + upb_strtable_iter_value(&i), + a); } - upb_strtable_uninit(t); + upb_strtable_uninit2(t, a); *t = new_table; return true; } -bool upb_strtable_insert2(upb_strtable *t, const char *k, size_t len, - upb_value v) { +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)) { + if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) { return false; } } key = strkey2(k, len); - tabkey = strcopy(key); + tabkey = strcopy(key, a); if (tabkey == 0) return false; hash = MurmurHash2(key.str.str, key.str.len, 0); @@ -4412,12 +4594,12 @@ bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len, return lookup(&t->t, strkey2(key, len), v, hash, &streql); } -bool upb_strtable_remove2(upb_strtable *t, const char *key, size_t len, - upb_value *val) { +bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len, + upb_value *val, upb_alloc *alloc) { uint32_t hash = MurmurHash2(key, strlen(key), 0); upb_tabkey tabkey; if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) { - free((void*)tabkey); + upb_free(alloc, (void*)tabkey); return true; } else { return false; @@ -4444,12 +4626,12 @@ bool upb_strtable_done(const upb_strtable_iter *i) { upb_tabent_isempty(str_tabent(i)); } -const char *upb_strtable_iter_key(upb_strtable_iter *i) { +const char *upb_strtable_iter_key(const upb_strtable_iter *i) { assert(!upb_strtable_done(i)); return upb_tabstr(str_tabent(i)->key, NULL); } -size_t upb_strtable_iter_keylength(upb_strtable_iter *i) { +size_t upb_strtable_iter_keylength(const upb_strtable_iter *i) { uint32_t len; assert(!upb_strtable_done(i)); upb_tabstr(str_tabent(i)->key, &len); @@ -4524,18 +4706,18 @@ static void check(upb_inttable *t) { } bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype, - size_t asize, int hsize_lg2) { + size_t asize, int hsize_lg2, upb_alloc *a) { size_t array_bytes; - if (!init(&t->t, ctype, hsize_lg2)) return false; + 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 = malloc(array_bytes); + t->array = upb_malloc(a, array_bytes); if (!t->array) { - uninit(&t->t); + uninit(&t->t, a); return false; } memset(mutable_array(t), 0xff, array_bytes); @@ -4543,22 +4725,23 @@ bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype, return true; } -bool upb_inttable_init(upb_inttable *t, upb_ctype_t ctype) { - return upb_inttable_sizedinit(t, ctype, 0, 4); +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_uninit(upb_inttable *t) { - uninit(&t->t); - free(mutable_array(t)); +void upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) { + uninit(&t->t, a); + upb_free(a, mutable_array(t)); } -bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val) { - /* XXX: Table can't store value (uint64_t)-1. Need to somehow statically - * guarantee that this is not necessary, or fix the limitation. */ +bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, + upb_alloc *a) { upb_tabval tabval; tabval.val = val.val; UPB_UNUSED(tabval); - assert(upb_arrhas(tabval)); + assert(upb_arrhas(tabval)); /* This will reject (uint64_t)-1. Fix this. */ + + upb_check_alloc(&t->t, a); if (key < t->array_size) { assert(!upb_arrhas(t->array[key])); @@ -4569,8 +4752,11 @@ bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val) { /* 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)) + + 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; @@ -4583,7 +4769,7 @@ bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val) { assert(t->t.count == new_table.count); - uninit(&t->t); + uninit(&t->t, a); t->t = new_table; } insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql); @@ -4629,8 +4815,9 @@ bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) { return success; } -bool upb_inttable_push(upb_inttable *t, upb_value val) { - return upb_inttable_insert(t, upb_inttable_count(t), val); +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) { @@ -4640,8 +4827,10 @@ upb_value upb_inttable_pop(upb_inttable *t) { return val; } -bool upb_inttable_insertptr(upb_inttable *t, const void *key, upb_value val) { - return upb_inttable_insert(t, (uintptr_t)key, 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, @@ -4653,7 +4842,7 @@ 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_compact(upb_inttable *t) { +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}; @@ -4665,6 +4854,8 @@ void upb_inttable_compact(upb_inttable *t) { 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); @@ -4697,16 +4888,16 @@ void upb_inttable_compact(upb_inttable *t) { 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); + 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_insert(&new_t, k, upb_inttable_iter_value(&i)); + upb_inttable_insert2(&new_t, k, upb_inttable_iter_value(&i), a); } assert(new_t.array_size == arr_size); assert(new_t.t.size_lg2 == hashsize_lg2); } - upb_inttable_uninit(t); + upb_inttable_uninit2(t, a); *t = new_t; } @@ -4982,6 +5173,19 @@ static void nullz(upb_status *status) { 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; @@ -5020,58 +5224,298 @@ void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) { nullz(status); } -void upb_status_seterrcode(upb_status *status, upb_errorspace *space, - int code) { - if (!status) return; - status->ok_ = false; - status->error_space_ = space; - status->code_ = code; - space->set_message(status, code); -} - void upb_status_copy(upb_status *to, const upb_status *from) { if (!to) return; *to = *from; } -/* This file was generated by upbc (the upb compiler). + + +/* 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(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(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(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; + } +} + +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. */ +#include <assert.h> + static const upb_msgdef msgs[22]; static const upb_fielddef fields[105]; static const upb_enumdef enums[5]; -static const upb_tabent strentries[268]; +static const upb_tabent strentries[236]; static const upb_tabent intentries[18]; static const upb_tabval arrays[184]; #ifdef UPB_DEBUG_REFS -static upb_inttable reftables[266]; +static upb_inttable reftables[264]; #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]),&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]),&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]),&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]),&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]),&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]),&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]),&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]),&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]),&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]),&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]),&reftables[20], &reftables[21]), - UPB_MSGDEF_INIT("google.protobuf.FileOptions", 31, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[68], 39, 15), UPB_STRTABLE_INIT(16, 31, UPB_CTYPE_PTR, 5, &strentries[92]),&reftables[22], &reftables[23]), - UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 10, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[8], &arrays[107], 8, 4), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[124]),&reftables[24], &reftables[25]), - UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 15, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[115], 7, 6), UPB_STRTABLE_INIT(6, 7, UPB_CTYPE_PTR, 3, &strentries[132]),&reftables[26], &reftables[27]), - UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[10], &arrays[122], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[140]),&reftables[28], &reftables[29]), - UPB_MSGDEF_INIT("google.protobuf.OneofDescriptorProto", 5, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[123], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[144]),&reftables[30], &reftables[31]), - UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[125], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[148]),&reftables[32], &reftables[33]), - UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[14], &arrays[129], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[152]),&reftables[34], &reftables[35]), - UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[130], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[156]),&reftables[36], &reftables[37]), - UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 19, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[132], 7, 5), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[160]),&reftables[38], &reftables[39]), - UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 18, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[139], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[168]),&reftables[40], &reftables[41]), - UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[148], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[184]),&reftables[42], &reftables[43]), + 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", 31, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[68], 39, 15), UPB_STRTABLE_INIT(16, 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[107], 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[115], 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[122], 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[123], 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[125], 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[129], 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[130], 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[132], 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[139], 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[148], 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[105] = { @@ -5084,18 +5528,18 @@ static const upb_fielddef fields[105] = { 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", 1, &msgs[6], NULL, 6, 1, {0},&reftables[62], &reftables[63]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[4], NULL, 7, 2, {0},&reftables[64], &reftables[65]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[17], NULL, 6, 1, {0},&reftables[66], &reftables[67]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[8], NULL, 8, 3, {0},&reftables[68], &reftables[69]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[14], 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[12], NULL, 8, 3, {0},&reftables[72], &reftables[73]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 23, &msgs[11], NULL, 21, 10, {0},&reftables[74], &reftables[75]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[12], NULL, 8, 3, {0},&reftables[62], &reftables[63]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[8], NULL, 8, 3, {0},&reftables[64], &reftables[65]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[14], NULL, 6, 1, {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", 3, &msgs[4], NULL, 7, 2, {0},&reftables[70], &reftables[71]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[17], NULL, 6, 1, {0},&reftables[72], &reftables[73]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 1, &msgs[6], 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_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 4, &msgs[0], (const upb_def*)(&msgs[3]), 18, 2, {0},&reftables[82], &reftables[83]), + 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[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]), @@ -5124,32 +5568,32 @@ static const upb_fielddef fields[105] = { 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_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[9], NULL, 22, 6, {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[13], NULL, 4, 1, {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[142], &reftables[143]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[15], NULL, 2, 0, {0},&reftables[144], &reftables[145]), + 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[146], &reftables[147]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[0], NULL, 32, 8, {0},&reftables[148], &reftables[149]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[3], 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[16], NULL, 8, 2, {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_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "name", 2, &msgs[20], (const upb_def*)(&msgs[21]), 5, 0, {0},&reftables[158], &reftables[159]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[5], NULL, 4, 1, {0},&reftables[150], &reftables[151]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[9], NULL, 22, 6, {0},&reftables[152], &reftables[153]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[7], 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[13], 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[16], NULL, 8, 2, {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_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 2, &msgs[5], NULL, 7, 2, {0},&reftables[168], &reftables[169]), + 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[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", 4, &msgs[13], (const upb_def*)(&msgs[14]), 3, 0, {0},&reftables[180], &reftables[181]), - 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[182], &reftables[183]), - 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[184], &reftables[185]), - 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[186], &reftables[187]), - 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[188], &reftables[189]), - 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[190], &reftables[191]), - 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[192], &reftables[193]), + 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", 4, &msgs[13], (const upb_def*)(&msgs[14]), 3, 0, {0},&reftables[184], &reftables[185]), + 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[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[5], (const upb_def*)(&msgs[6]), 3, 0, {0},&reftables[190], &reftables[191]), + 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[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]), @@ -5163,20 +5607,20 @@ static const upb_fielddef fields[105] = { 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[214], &reftables[215]), 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[216], &reftables[217]), 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[218], &reftables[219]), - 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[220], &reftables[221]), - 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[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[220], &reftables[221]), + 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[222], &reftables[223]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, false, "string_value", 7, &msgs[20], NULL, 12, 5, {0},&reftables[224], &reftables[225]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "syntax", 12, &msgs[9], NULL, 39, 11, {0},&reftables[226], &reftables[227]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "trailing_comments", 4, &msgs[19], NULL, 11, 3, {0},&reftables[228], &reftables[229]), 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[230], &reftables[231]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "type_name", 6, &msgs[7], NULL, 13, 6, {0},&reftables[232], &reftables[233]), - 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[234], &reftables[235]), + 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[234], &reftables[235]), 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[236], &reftables[237]), - 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[238], &reftables[239]), - 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[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[4], (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[6], (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[238], &reftables[239]), + 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[240], &reftables[241]), + 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[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[17], (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, "value", 2, &msgs[3], (const upb_def*)(&msgs[5]), 6, 0, {0},&reftables[248], &reftables[249]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "weak", 10, &msgs[8], NULL, 11, 6, {0},&reftables[250], &reftables[251]), 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[252], &reftables[253]), @@ -5190,7 +5634,7 @@ static const upb_enumdef enums[5] = { 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[180], 4, 3), 0, &reftables[262], &reftables[263]), }; -static const upb_tabent strentries[268] = { +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[82]), NULL}, @@ -5204,50 +5648,50 @@ static const upb_tabent strentries[268] = { {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[83]), NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[70]), 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[88]), NULL}, + {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[19]), &strentries[13]}, + {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[89]), 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[89]), NULL}, + {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[88]), 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[102]), NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[69]), NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[53]), &strentries[26]}, - {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_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[49]), &strentries[26]}, + {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[13]), 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_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[62]), NULL}, {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[71]), 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[101]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[9]), 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[53]), &strentries[34]}, + {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[15]), 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_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[55]), 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_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[63]), &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[94]), 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[93]), &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[74]), NULL}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[97]), 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[99]), NULL}, {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "weak"), UPB_TABVALUE_PTR_INIT(&fields[103]), NULL}, {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, @@ -5260,13 +5704,13 @@ static const upb_tabent strentries[268] = { {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[12]), 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_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[104]), 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_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[54]), NULL}, {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "service"), UPB_TABVALUE_PTR_INIT(&fields[85]), NULL}, {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "source_code_info"), UPB_TABVALUE_PTR_INIT(&fields[86]), NULL}, @@ -5276,8 +5720,8 @@ static const upb_tabent strentries[268] = { {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[72]), &strentries[86]}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[19]), 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[20]), NULL}, {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "public_dependency"), UPB_TABVALUE_PTR_INIT(&fields[80]), &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}, @@ -5299,7 +5743,7 @@ static const upb_tabent strentries[268] = { {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("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL}, + {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[95]), 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}, @@ -5312,7 +5756,7 @@ static const upb_tabent strentries[268] = { {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "py_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[81]), 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[15]), &strentries[119]}, + {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]}, @@ -5320,31 +5764,31 @@ static const upb_tabent strentries[268] = { {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[96]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL}, + {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[9]), 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[84]), NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[51]), NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[56]), 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[68]), NULL}, - {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[13]), 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[100]), NULL}, + {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[11]), 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_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[50]), NULL}, {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[73]), &strentries[150]}, + {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[55]), &strentries[149]}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[95]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[11]), NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[57]), &strentries[149]}, + {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL}, + {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[14]), 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}, @@ -5362,7 +5806,7 @@ static const upb_tabent strentries[268] = { {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[57]), NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[51]), 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}, @@ -5427,59 +5871,27 @@ static const upb_tabent strentries[268] = { {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}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\047", "\000", "\000", "\000", "google.protobuf.SourceCodeInfo.Location"), UPB_TABVALUE_PTR_INIT(&msgs[19]), NULL}, - {UPB_TABKEY_STR("\043", "\000", "\000", "\000", "google.protobuf.UninterpretedOption"), UPB_TABVALUE_PTR_INIT(&msgs[20]), NULL}, - {UPB_TABKEY_STR("\043", "\000", "\000", "\000", "google.protobuf.FileDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[9]), NULL}, - {UPB_TABKEY_STR("\045", "\000", "\000", "\000", "google.protobuf.MethodDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[13]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\040", "\000", "\000", "\000", "google.protobuf.EnumValueOptions"), UPB_TABVALUE_PTR_INIT(&msgs[6]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\055", "\000", "\000", "\000", "google.protobuf.DescriptorProto.ReservedRange"), UPB_TABVALUE_PTR_INIT(&msgs[2]), NULL}, - {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "google.protobuf.DescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[0]), &strentries[248]}, - {UPB_TABKEY_STR("\041", "\000", "\000", "\000", "google.protobuf.FileDescriptorSet"), UPB_TABVALUE_PTR_INIT(&msgs[10]), &strentries[267]}, - {UPB_TABKEY_STR("\036", "\000", "\000", "\000", "google.protobuf.SourceCodeInfo"), UPB_TABVALUE_PTR_INIT(&msgs[18]), NULL}, - {UPB_TABKEY_STR("\051", "\000", "\000", "\000", "google.protobuf.FieldDescriptorProto.Type"), UPB_TABVALUE_PTR_INIT(&enums[1]), NULL}, - {UPB_TABKEY_STR("\056", "\000", "\000", "\000", "google.protobuf.DescriptorProto.ExtensionRange"), UPB_TABVALUE_PTR_INIT(&msgs[1]), NULL}, - {UPB_TABKEY_STR("\044", "\000", "\000", "\000", "google.protobuf.OneofDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[15]), NULL}, - {UPB_TABKEY_STR("\046", "\000", "\000", "\000", "google.protobuf.ServiceDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[16]), NULL}, - {UPB_TABKEY_STR("\034", "\000", "\000", "\000", "google.protobuf.FieldOptions"), UPB_TABVALUE_PTR_INIT(&msgs[8]), NULL}, - {UPB_TABKEY_STR("\033", "\000", "\000", "\000", "google.protobuf.FileOptions"), UPB_TABVALUE_PTR_INIT(&msgs[11]), NULL}, - {UPB_TABKEY_STR("\043", "\000", "\000", "\000", "google.protobuf.EnumDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[3]), &strentries[265]}, - {UPB_TABKEY_STR("\052", "\000", "\000", "\000", "google.protobuf.FieldDescriptorProto.Label"), UPB_TABVALUE_PTR_INIT(&enums[0]), NULL}, - {UPB_TABKEY_STR("\050", "\000", "\000", "\000", "google.protobuf.FileOptions.OptimizeMode"), UPB_TABVALUE_PTR_INIT(&enums[4]), NULL}, - {UPB_TABKEY_STR("\042", "\000", "\000", "\000", "google.protobuf.FieldOptions.CType"), UPB_TABVALUE_PTR_INIT(&enums[2]), &strentries[261]}, - {UPB_TABKEY_STR("\043", "\000", "\000", "\000", "google.protobuf.FieldOptions.JSType"), UPB_TABVALUE_PTR_INIT(&enums[3]), NULL}, - {UPB_TABKEY_STR("\033", "\000", "\000", "\000", "google.protobuf.EnumOptions"), UPB_TABVALUE_PTR_INIT(&msgs[4]), NULL}, - {UPB_TABKEY_STR("\044", "\000", "\000", "\000", "google.protobuf.FieldDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[7]), NULL}, - {UPB_TABKEY_STR("\050", "\000", "\000", "\000", "google.protobuf.EnumValueDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[5]), &strentries[258]}, - {UPB_TABKEY_STR("\036", "\000", "\000", "\000", "google.protobuf.ServiceOptions"), UPB_TABVALUE_PTR_INIT(&msgs[17]), NULL}, - {UPB_TABKEY_STR("\036", "\000", "\000", "\000", "google.protobuf.MessageOptions"), UPB_TABVALUE_PTR_INIT(&msgs[12]), NULL}, - {UPB_TABKEY_STR("\035", "\000", "\000", "\000", "google.protobuf.MethodOptions"), UPB_TABVALUE_PTR_INIT(&msgs[14]), &strentries[253]}, - {UPB_TABKEY_STR("\054", "\000", "\000", "\000", "google.protobuf.UninterpretedOption.NamePart"), UPB_TABVALUE_PTR_INIT(&msgs[21]), NULL}, }; static const upb_tabent intentries[18] = { {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(999), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL}, + {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[98]), 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(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[95]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL}, {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[13]), NULL}, + {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[11]), NULL}, {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[98]), 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[11]), NULL}, + {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL}, {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[95]), NULL}, + {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL}, }; static const upb_tabval arrays[184] = { @@ -5487,48 +5899,48 @@ static const upb_tabval arrays[184] = { UPB_TABVALUE_PTR_INIT(&fields[52]), UPB_TABVALUE_PTR_INIT(&fields[25]), UPB_TABVALUE_PTR_INIT(&fields[60]), - UPB_TABVALUE_PTR_INIT(&fields[20]), + UPB_TABVALUE_PTR_INIT(&fields[19]), UPB_TABVALUE_PTR_INIT(&fields[24]), UPB_TABVALUE_PTR_INIT(&fields[22]), - UPB_TABVALUE_PTR_INIT(&fields[70]), + UPB_TABVALUE_PTR_INIT(&fields[68]), UPB_TABVALUE_PTR_INIT(&fields[65]), UPB_TABVALUE_PTR_INIT(&fields[83]), UPB_TABVALUE_PTR_INIT(&fields[82]), UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[88]), + UPB_TABVALUE_PTR_INIT(&fields[89]), UPB_TABVALUE_PTR_INIT(&fields[18]), UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[89]), + UPB_TABVALUE_PTR_INIT(&fields[88]), UPB_TABVALUE_PTR_INIT(&fields[17]), UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[53]), + UPB_TABVALUE_PTR_INIT(&fields[49]), UPB_TABVALUE_PTR_INIT(&fields[102]), - UPB_TABVALUE_PTR_INIT(&fields[69]), + UPB_TABVALUE_PTR_INIT(&fields[74]), UPB_TABVALUE_EMPTY_INIT, UPB_TABVALUE_EMPTY_INIT, UPB_TABVALUE_PTR_INIT(&fields[1]), - UPB_TABVALUE_PTR_INIT(&fields[10]), + UPB_TABVALUE_PTR_INIT(&fields[13]), UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[50]), - UPB_TABVALUE_PTR_INIT(&fields[63]), - UPB_TABVALUE_PTR_INIT(&fields[71]), + UPB_TABVALUE_PTR_INIT(&fields[53]), + UPB_TABVALUE_PTR_INIT(&fields[62]), + UPB_TABVALUE_PTR_INIT(&fields[73]), UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[9]), + UPB_TABVALUE_PTR_INIT(&fields[15]), UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[56]), + UPB_TABVALUE_PTR_INIT(&fields[55]), UPB_TABVALUE_PTR_INIT(&fields[21]), - UPB_TABVALUE_PTR_INIT(&fields[62]), + UPB_TABVALUE_PTR_INIT(&fields[63]), UPB_TABVALUE_PTR_INIT(&fields[40]), UPB_TABVALUE_PTR_INIT(&fields[93]), UPB_TABVALUE_PTR_INIT(&fields[94]), UPB_TABVALUE_PTR_INIT(&fields[7]), - UPB_TABVALUE_PTR_INIT(&fields[74]), + UPB_TABVALUE_PTR_INIT(&fields[71]), 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[12]), + UPB_TABVALUE_PTR_INIT(&fields[10]), UPB_TABVALUE_EMPTY_INIT, UPB_TABVALUE_PTR_INIT(&fields[41]), UPB_TABVALUE_PTR_INIT(&fields[39]), @@ -5537,14 +5949,14 @@ static const upb_tabval arrays[184] = { UPB_TABVALUE_EMPTY_INIT, UPB_TABVALUE_PTR_INIT(&fields[103]), UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[49]), + UPB_TABVALUE_PTR_INIT(&fields[54]), 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[20]), UPB_TABVALUE_PTR_INIT(&fields[85]), UPB_TABVALUE_PTR_INIT(&fields[23]), - UPB_TABVALUE_PTR_INIT(&fields[72]), + UPB_TABVALUE_PTR_INIT(&fields[69]), UPB_TABVALUE_PTR_INIT(&fields[86]), UPB_TABVALUE_PTR_INIT(&fields[80]), UPB_TABVALUE_PTR_INIT(&fields[104]), @@ -5574,7 +5986,7 @@ static const upb_tabval arrays[184] = { UPB_TABVALUE_PTR_INIT(&fields[31]), UPB_TABVALUE_EMPTY_INIT, UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[15]), + UPB_TABVALUE_PTR_INIT(&fields[12]), UPB_TABVALUE_EMPTY_INIT, UPB_TABVALUE_EMPTY_INIT, UPB_TABVALUE_EMPTY_INIT, @@ -5593,25 +6005,25 @@ static const upb_tabval arrays[184] = { UPB_TABVALUE_EMPTY_INIT, UPB_TABVALUE_PTR_INIT(&fields[46]), UPB_TABVALUE_PTR_INIT(&fields[61]), - UPB_TABVALUE_PTR_INIT(&fields[14]), + UPB_TABVALUE_PTR_INIT(&fields[9]), 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[51]), + UPB_TABVALUE_PTR_INIT(&fields[56]), UPB_TABVALUE_PTR_INIT(&fields[29]), UPB_TABVALUE_PTR_INIT(&fields[75]), - UPB_TABVALUE_PTR_INIT(&fields[68]), + UPB_TABVALUE_PTR_INIT(&fields[70]), UPB_TABVALUE_PTR_INIT(&fields[4]), UPB_TABVALUE_PTR_INIT(&fields[84]), UPB_TABVALUE_EMPTY_INIT, UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[54]), + UPB_TABVALUE_PTR_INIT(&fields[50]), UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[55]), + UPB_TABVALUE_PTR_INIT(&fields[57]), UPB_TABVALUE_PTR_INIT(&fields[48]), - UPB_TABVALUE_PTR_INIT(&fields[73]), + UPB_TABVALUE_PTR_INIT(&fields[72]), UPB_TABVALUE_EMPTY_INIT, UPB_TABVALUE_EMPTY_INIT, UPB_TABVALUE_PTR_INIT(&fields[44]), @@ -5624,7 +6036,7 @@ static const upb_tabval arrays[184] = { UPB_TABVALUE_PTR_INIT(&fields[43]), UPB_TABVALUE_EMPTY_INIT, UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[57]), + UPB_TABVALUE_PTR_INIT(&fields[51]), UPB_TABVALUE_PTR_INIT(&fields[28]), UPB_TABVALUE_PTR_INIT(&fields[79]), UPB_TABVALUE_PTR_INIT(&fields[59]), @@ -5669,17 +6081,8 @@ static const upb_tabval arrays[184] = { UPB_TABVALUE_PTR_INIT("LITE_RUNTIME"), }; -static const upb_symtab symtab = UPB_SYMTAB_INIT(UPB_STRTABLE_INIT(27, 31, UPB_CTYPE_PTR, 5, &strentries[236]), &reftables[264], &reftables[265]); - -const upb_symtab *upbdefs_google_protobuf_descriptor(const void *owner) { - upb_symtab_ref(&symtab, owner); - return &symtab; -} - #ifdef UPB_DEBUG_REFS -static upb_inttable reftables[266] = { - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), +static upb_inttable reftables[264] = { UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), @@ -5947,6 +6350,45 @@ static upb_inttable reftables[266] = { }; #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 @@ -5965,15 +6407,6 @@ static bool upb_streq(const char *str, const char *buf, size_t n) { return strlen(str) == n && memcmp(str, buf, n) == 0; } -/* upb_deflist is an internal-only dynamic array for storing a growing list of - * upb_defs. */ -typedef struct { - upb_def **defs; - size_t len; - size_t size; - bool owned; -} upb_deflist; - /* 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 @@ -5999,13 +6432,11 @@ typedef struct { struct upb_descreader { upb_sink sink; - upb_deflist defs; + upb_inttable files; + upb_filedef *file; /* The last file in files. */ upb_descreader_frame stack[UPB_MAX_MESSAGE_NESTING]; int stack_len; - bool primitives_have_presence; - int file_start; - uint32_t number; char *name; bool saw_number; @@ -6017,7 +6448,7 @@ struct upb_descreader { }; static char *upb_strndup(const char *buf, size_t n) { - char *ret = malloc(n + 1); + char *ret = upb_gmalloc(n + 1); if (!ret) return NULL; memcpy(ret, buf, n); ret[n] = '\0'; @@ -6031,9 +6462,12 @@ static char *upb_strndup(const char *buf, size_t n) { * 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_strdup(name); + return upb_gstrdup(name); } else { - char *ret = malloc(strlen(base) + strlen(name) + 2); + char *ret = upb_gmalloc(strlen(base) + strlen(name) + 2); + if (!ret) { + return NULL; + } ret[0] = '\0'; strcat(ret, base); strcat(ret, "."); @@ -6042,57 +6476,21 @@ static char *upb_join(const char *base, const char *name) { } } - -/* upb_deflist ****************************************************************/ - -void upb_deflist_init(upb_deflist *l) { - l->size = 0; - l->defs = NULL; - l->len = 0; - l->owned = true; -} - -void upb_deflist_uninit(upb_deflist *l) { - size_t i; - if (l->owned) - for(i = 0; i < l->len; i++) - upb_def_unref(l->defs[i], l); - free(l->defs); -} - -bool upb_deflist_push(upb_deflist *l, upb_def *d) { - if(++l->len >= l->size) { - size_t new_size = UPB_MAX(l->size, 4); - new_size *= 2; - l->defs = realloc(l->defs, new_size * sizeof(void *)); - if (!l->defs) return false; - l->size = new_size; - } - l->defs[l->len - 1] = d; - return true; -} - -void upb_deflist_donaterefs(upb_deflist *l, void *owner) { - size_t i; - assert(l->owned); - for (i = 0; i < l->len; i++) - upb_def_donateref(l->defs[i], l, owner); - l->owned = false; -} - -static upb_def *upb_deflist_last(upb_deflist *l) { - return l->defs[l->len-1]; -} - /* Qualify the defname for all defs starting with offset "start" with "str". */ -static void upb_deflist_qualify(upb_deflist *l, char *str, int32_t start) { - uint32_t i; - for (i = start; i < l->len; i++) { - upb_def *def = l->defs[i]; +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); - free(name); + upb_gfree(name); } + return true; } @@ -6103,92 +6501,144 @@ static upb_msgdef *upb_descreader_top(upb_descreader *r) { assert(r->stack_len > 1); index = r->stack[r->stack_len-1].start - 1; assert(index >= 0); - return upb_downcast_msgdef_mutable(r->defs.defs[index]); + return upb_downcast_msgdef_mutable(upb_filedef_mutabledef(r->file, index)); } static upb_def *upb_descreader_last(upb_descreader *r) { - return upb_deflist_last(&r->defs); + 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 = r->defs.len; + f->start = upb_filedef_defcount(r->file); f->name = NULL; } -void upb_descreader_endcontainer(upb_descreader *r) { +bool upb_descreader_endcontainer(upb_descreader *r) { upb_descreader_frame *f = &r->stack[--r->stack_len]; - upb_deflist_qualify(&r->defs, f->name, f->start); - free(f->name); + if (!upb_descreader_qualify(r->file, f->name, f->start)) { + return false; + } + upb_gfree(f->name); f->name = NULL; + return true; } void upb_descreader_setscopename(upb_descreader *r, char *str) { upb_descreader_frame *f = &r->stack[r->stack_len-1]; - free(f->name); + upb_gfree(f->name); f->name = str; } -/* Handlers for google.protobuf.FileDescriptorProto. */ -static bool file_startmsg(void *closure, const void *hd) { +/** 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); - r->primitives_have_presence = true; - r->file_start = r->defs.len; return true; } -static bool file_endmsg(void *closure, const void *hd, upb_status *status) { +static bool file_end(void *closure, const void *hd, upb_status *status) { upb_descreader *r = closure; UPB_UNUSED(hd); UPB_UNUSED(status); - upb_descreader_endcontainer(r); - return true; + 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_strndup(buf, n); + /* XXX: see comment at the top of the file. */ + ok = upb_filedef_setname(r->file, name, NULL); + upb_gfree(name); + UPB_ASSERT_VAR(ok, 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_strndup(buf, n); /* XXX: see comment at the top of the file. */ - upb_descreader_setscopename(r, upb_strndup(buf, n)); + upb_descreader_setscopename(r, package); + ok = upb_filedef_setpackage(r->file, package, NULL); + UPB_ASSERT_VAR(ok, 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)) { - /* Technically we could verify that proto3 hadn't previously been seen. */ + ok = upb_filedef_setsyntax(r->file, UPB_SYNTAX_PROTO2, NULL); } else if (upb_streq("proto3", buf, n)) { - uint32_t i; - /* Update messages created before the syntax was read. */ - for (i = r->file_start; i < r->defs.len; i++) { - upb_msgdef *m = upb_dyncast_msgdef_mutable(r->defs.defs[i]); - if (m) { - upb_msgdef_setprimitiveshavepresence(m, false); - } - } - - /* Set a flag for any future messages that will be created. */ - r->primitives_have_presence = false; + ok = upb_filedef_setsyntax(r->file, UPB_SYNTAX_PROTO3, NULL); } else { - /* Error: neither proto3 nor proto3. - * TODO(haberman): there should be a status object we can report this to. */ - return 0; + ok = false; } + UPB_ASSERT_VAR(ok, ok); return n; } -/* Handlers for google.protobuf.EnumValueDescriptorProto. */ +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_VAR(ok, 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_VAR(ok, 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_VAR(ok, ok); + return r; +} + +/** Handlers for google.protobuf.EnumValueDescriptorProto. *********************/ + static bool enumval_startmsg(void *closure, const void *hd) { upb_descreader *r = closure; UPB_UNUSED(hd); @@ -6203,7 +6653,7 @@ static size_t enumval_onname(void *closure, const void *hd, const char *buf, UPB_UNUSED(hd); UPB_UNUSED(handle); /* XXX: see comment at the top of the file. */ - free(r->name); + upb_gfree(r->name); r->name = upb_strndup(buf, n); r->saw_name = true; return n; @@ -6228,20 +6678,12 @@ static bool enumval_endmsg(void *closure, const void *hd, upb_status *status) { } e = upb_downcast_enumdef_mutable(upb_descreader_last(r)); upb_enumdef_addval(e, r->name, r->number, status); - free(r->name); + upb_gfree(r->name); r->name = NULL; return true; } - -/* Handlers for google.protobuf.EnumDescriptorProto. */ -static bool enum_startmsg(void *closure, const void *hd) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - upb_deflist_push(&r->defs, - upb_enumdef_upcast_mutable(upb_enumdef_new(&r->defs))); - return true; -} +/** Handlers for google.protobuf.EnumDescriptorProto. *************************/ static bool enum_endmsg(void *closure, const void *hd, upb_status *status) { upb_descreader *r = closure; @@ -6268,16 +6710,17 @@ static size_t enum_onname(void *closure, const void *hd, const char *buf, UPB_UNUSED(handle); /* XXX: see comment at the top of the file. */ upb_def_setfullname(upb_descreader_last(r), fullname, NULL); - free(fullname); + upb_gfree(fullname); return n; } -/* Handlers for google.protobuf.FieldDescriptorProto */ +/** Handlers for google.protobuf.FieldDescriptorProto *************************/ + static bool field_startmsg(void *closure, const void *hd) { upb_descreader *r = closure; UPB_UNUSED(hd); - r->f = upb_fielddef_new(&r->defs); - free(r->default_string); + assert(r->f); + upb_gfree(r->default_string); r->default_string = NULL; /* fielddefs default to packed, but descriptors default to non-packed. */ @@ -6419,9 +6862,10 @@ static bool field_onlabel(void *closure, const void *hd, int32_t val) { static bool field_onnumber(void *closure, const void *hd, int32_t val) { upb_descreader *r = closure; - bool ok = upb_fielddef_setnumber(r->f, val, NULL); + bool ok; UPB_UNUSED(hd); + ok = upb_fielddef_setnumber(r->f, val, NULL); UPB_ASSERT_VAR(ok, ok); return true; } @@ -6435,7 +6879,7 @@ static size_t field_onname(void *closure, const void *hd, const char *buf, /* XXX: see comment at the top of the file. */ upb_fielddef_setname(r->f, name, NULL); - free(name); + upb_gfree(name); return n; } @@ -6448,7 +6892,7 @@ static size_t field_ontypename(void *closure, const void *hd, const char *buf, /* XXX: see comment at the top of the file. */ upb_fielddef_setsubdefname(r->f, name, NULL); - free(name); + upb_gfree(name); return n; } @@ -6461,7 +6905,7 @@ static size_t field_onextendee(void *closure, const void *hd, const char *buf, /* XXX: see comment at the top of the file. */ upb_fielddef_setcontainingtypename(r->f, name, NULL); - free(name); + upb_gfree(name); return n; } @@ -6474,25 +6918,22 @@ static size_t field_ondefaultval(void *closure, const void *hd, const char *buf, /* 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. */ - free(r->default_string); + upb_gfree(r->default_string); r->default_string = upb_strndup(buf, n); return n; } -/* Handlers for google.protobuf.DescriptorProto (representing a message). */ -static bool msg_startmsg(void *closure, const void *hd) { +/** Handlers for google.protobuf.DescriptorProto ******************************/ + +static bool msg_start(void *closure, const void *hd) { upb_descreader *r = closure; - upb_msgdef *m; UPB_UNUSED(hd); - m = upb_msgdef_new(&r->defs); - upb_msgdef_setprimitiveshavepresence(m, r->primitives_have_presence); - upb_deflist_push(&r->defs, upb_msgdef_upcast_mutable(m)); upb_descreader_startcontainer(r); return true; } -static bool msg_endmsg(void *closure, const void *hd, upb_status *status) { +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); @@ -6501,12 +6942,11 @@ static bool msg_endmsg(void *closure, const void *hd, upb_status *status) { upb_status_seterrmsg(status, "Encountered message with no name."); return false; } - upb_descreader_endcontainer(r); - return true; + return upb_descreader_endcontainer(r); } -static size_t msg_onname(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { +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. */ @@ -6519,93 +6959,147 @@ static size_t msg_onname(void *closure, const void *hd, const char *buf, return n; } -static bool msg_onendfield(void *closure, const void *hd) { +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_VAR(ok, 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_VAR(ok, 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); UPB_UNUSED(hd); - upb_msgdef_addfield(m, r->f, &r->defs, NULL); + upb_msgdef_addfield(m, r->f, &r->f, NULL); r->f = NULL; return true; } -static bool pushextension(void *closure, const void *hd) { +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); - assert(upb_fielddef_containingtypename(r->f)); - upb_fielddef_setisextension(r->f, true); - upb_deflist_push(&r->defs, upb_fielddef_upcast_mutable(r->f)); + upb_msgdef_setmapentry(m, mapentry); r->f = NULL; return true; } -#define D(name) upbdefs_google_protobuf_ ## name(s) + + +/** 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_symtab *s = closure; const upb_msgdef *m = upb_handlers_msgdef(h); + UPB_UNUSED(closure); - if (m == D(DescriptorProto)) { - upb_handlers_setstartmsg(h, &msg_startmsg, NULL); - upb_handlers_setendmsg(h, &msg_endmsg, NULL); - upb_handlers_setstring(h, D(DescriptorProto_name), &msg_onname, NULL); - upb_handlers_setendsubmsg(h, D(DescriptorProto_field), &msg_onendfield, - NULL); - upb_handlers_setendsubmsg(h, D(DescriptorProto_extension), &pushextension, - NULL); - } else if (m == D(FileDescriptorProto)) { - upb_handlers_setstartmsg(h, &file_startmsg, NULL); - upb_handlers_setendmsg(h, &file_endmsg, NULL); - upb_handlers_setstring(h, D(FileDescriptorProto_package), &file_onpackage, + 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, D(FileDescriptorProto_syntax), &file_onsyntax, + upb_handlers_setstring(h, F(FileDescriptorProto, package), &file_onpackage, NULL); - upb_handlers_setendsubmsg(h, D(FileDescriptorProto_extension), &pushextension, - NULL); - } else if (m == D(EnumValueDescriptorProto)) { + 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, D(EnumValueDescriptorProto_name), &enumval_onname, NULL); - upb_handlers_setint32(h, D(EnumValueDescriptorProto_number), &enumval_onnumber, + upb_handlers_setstring(h, F(EnumValueDescriptorProto, name), &enumval_onname, NULL); + upb_handlers_setint32(h, F(EnumValueDescriptorProto, number), &enumval_onnumber, NULL); - } else if (m == D(EnumDescriptorProto)) { - upb_handlers_setstartmsg(h, &enum_startmsg, NULL); + } else if (upbdefs_google_protobuf_EnumDescriptorProto_is(m)) { upb_handlers_setendmsg(h, &enum_endmsg, NULL); - upb_handlers_setstring(h, D(EnumDescriptorProto_name), &enum_onname, NULL); - } else if (m == D(FieldDescriptorProto)) { + 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, D(FieldDescriptorProto_type), &field_ontype, + upb_handlers_setint32(h, F(FieldDescriptorProto, type), &field_ontype, NULL); - upb_handlers_setint32(h, D(FieldDescriptorProto_label), &field_onlabel, + upb_handlers_setint32(h, F(FieldDescriptorProto, label), &field_onlabel, NULL); - upb_handlers_setint32(h, D(FieldDescriptorProto_number), &field_onnumber, + upb_handlers_setint32(h, F(FieldDescriptorProto, number), &field_onnumber, NULL); - upb_handlers_setstring(h, D(FieldDescriptorProto_name), &field_onname, + upb_handlers_setstring(h, F(FieldDescriptorProto, name), &field_onname, NULL); - upb_handlers_setstring(h, D(FieldDescriptorProto_type_name), + upb_handlers_setstring(h, F(FieldDescriptorProto, type_name), &field_ontypename, NULL); - upb_handlers_setstring(h, D(FieldDescriptorProto_extendee), + upb_handlers_setstring(h, F(FieldDescriptorProto, extendee), &field_onextendee, NULL); - upb_handlers_setstring(h, D(FieldDescriptorProto_default_value), + upb_handlers_setstring(h, F(FieldDescriptorProto, default_value), &field_ondefaultval, NULL); - } else if (m == D(FieldOptions)) { - upb_handlers_setbool(h, D(FieldOptions_lazy), &field_onlazy, NULL); - upb_handlers_setbool(h, D(FieldOptions_packed), &field_onpacked, 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); } + + assert(upb_ok(upb_handlers_status(h))); } -#undef D +#undef F void descreader_cleanup(void *_r) { upb_descreader *r = _r; - free(r->name); - upb_deflist_uninit(&r->defs); - free(r->default_string); + 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_gfree(r->default_string); while (r->stack_len > 0) { upb_descreader_frame *f = &r->stack[--r->stack_len]; - free(f->name); + upb_gfree(f->name); } } @@ -6618,7 +7112,7 @@ upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h) { return NULL; } - upb_deflist_init(&r->defs); + upb_inttable_init(&r->files, UPB_CTYPE_PTR); upb_sink_reset(upb_descreader_input(r), h, r); r->stack_len = 0; r->name = NULL; @@ -6627,10 +7121,17 @@ upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h) { return r; } -upb_def **upb_descreader_getdefs(upb_descreader *r, void *owner, int *n) { - *n = r->defs.len; - upb_deflist_donaterefs(&r->defs, owner); - return r->defs.defs; +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) { @@ -6638,10 +7139,9 @@ upb_sink *upb_descreader_input(upb_descreader *r) { } const upb_handlers *upb_descreader_newhandlers(const void *owner) { - const upb_symtab *s = upbdefs_google_protobuf_descriptor(&s); - const upb_handlers *h = upb_handlers_newfrozen( - upbdefs_google_protobuf_FileDescriptorSet(s), owner, reghandlers, s); - upb_symtab_unref(s, &s); + 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; } /* @@ -6675,8 +7175,8 @@ static void freegroup(upb_refcounted *r) { #ifdef UPB_USE_JIT_X64 upb_pbdecoder_freejit(g); #endif - free(g->bytecode); - free(g); + upb_gfree(g->bytecode); + upb_gfree(g); } static void visitgroup(const upb_refcounted *r, upb_refcounted_visit *visit, @@ -6691,7 +7191,7 @@ static void visitgroup(const upb_refcounted *r, upb_refcounted_visit *visit, } mgroup *newgroup(const void *owner) { - mgroup *g = malloc(sizeof(*g)); + 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); @@ -6711,7 +7211,7 @@ static void freemethod(upb_refcounted *r) { } upb_inttable_uninit(&method->dispatch); - free(method); + upb_gfree(method); } static void visitmethod(const upb_refcounted *r, upb_refcounted_visit *visit, @@ -6723,7 +7223,7 @@ static void visitmethod(const upb_refcounted *r, upb_refcounted_visit *visit, static upb_pbdecodermethod *newmethod(const upb_handlers *dest_handlers, mgroup *group) { static const struct upb_refcounted_vtbl vtbl = {visitmethod, freemethod}; - upb_pbdecodermethod *ret = malloc(sizeof(*ret)); + upb_pbdecodermethod *ret = upb_gmalloc(sizeof(*ret)); upb_refcounted_init(upb_pbdecodermethod_upcast_mutable(ret), &vtbl, &ret); upb_byteshandler_init(&ret->input_handler_); @@ -6786,7 +7286,7 @@ typedef struct { } compiler; static compiler *newcompiler(mgroup *group, bool lazy) { - compiler *ret = malloc(sizeof(*ret)); + compiler *ret = upb_gmalloc(sizeof(*ret)); int i; ret->group = group; @@ -6799,7 +7299,7 @@ static compiler *newcompiler(mgroup *group, bool lazy) { } static void freecompiler(compiler *c) { - free(c); + upb_gfree(c); } const size_t ptr_words = sizeof(void*) / sizeof(uint32_t); @@ -6903,7 +7403,8 @@ static void put32(compiler *c, uint32_t v) { size_t oldsize = g->bytecode_end - g->bytecode; size_t newsize = UPB_MAX(oldsize * 2, 64); /* TODO(haberman): handle OOM. */ - g->bytecode = realloc(g->bytecode, newsize * sizeof(uint32_t)); + 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; } @@ -8768,7 +9269,6 @@ bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) { */ -#include <stdlib.h> /* 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 @@ -9013,12 +9513,12 @@ 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 = malloc(sizeof(tag_t)); + 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, free); + upb_handlers_addcleanup(h, tag, upb_gfree); } static bool encode_tag(upb_pb_encoder *e, const tag_t *tag) { @@ -9277,12 +9777,9 @@ upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h, upb_sink *upb_pb_encoder_input(upb_pb_encoder *e) { return &e->input_; } -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n, - void *owner, upb_status *status) { +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); @@ -9291,8 +9788,8 @@ upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n, upb_pbdecoder *decoder; upb_descreader *reader; bool ok; - upb_def **ret = NULL; - upb_def **defs; + size_t i; + upb_filedef **ret = NULL; upb_pbdecodermethodopts_init(&opts, reader_h); decoder_m = upb_pbdecodermethod_new(&opts, &decoder_m); @@ -9304,12 +9801,24 @@ upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n, decoder = upb_pbdecoder_create(&env, decoder_m, upb_descreader_input(reader)); /* Push input data. */ - ok = upb_bufsrc_putbuf(str, len, upb_pbdecoder_input(decoder)); + 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); + } - if (!ok) goto cleanup; - defs = upb_descreader_getdefs(reader, owner, n); - ret = malloc(sizeof(upb_def*) * (*n)); - memcpy(ret, defs, sizeof(upb_def*) * (*n)); + ret[i] = NULL; cleanup: upb_env_uninit(&env); @@ -9317,51 +9826,6 @@ cleanup: upb_pbdecodermethod_unref(decoder_m, &decoder_m); return ret; } - -bool upb_load_descriptor_into_symtab(upb_symtab *s, const char *str, size_t len, - upb_status *status) { - int n; - bool success; - upb_def **defs = upb_load_defs_from_descriptor(str, len, &n, &defs, status); - if (!defs) return false; - success = upb_symtab_add(s, defs, n, &defs, status); - free(defs); - return success; -} - -char *upb_readfile(const char *filename, size_t *len) { - long size; - char *buf; - FILE *f = fopen(filename, "rb"); - if(!f) return NULL; - if(fseek(f, 0, SEEK_END) != 0) goto error; - size = ftell(f); - if(size < 0) goto error; - if(fseek(f, 0, SEEK_SET) != 0) goto error; - buf = malloc(size + 1); - if(size && fread(buf, size, 1, f) != 1) goto error; - fclose(f); - if (len) *len = size; - return buf; - -error: - fclose(f); - return NULL; -} - -bool upb_load_descriptor_file_into_symtab(upb_symtab *symtab, const char *fname, - upb_status *status) { - size_t len; - bool success; - char *data = upb_readfile(fname, &len); - if (!data) { - if (status) upb_status_seterrf(status, "Couldn't read file: %s", fname); - return false; - } - success = upb_load_descriptor_into_symtab(symtab, data, len, status); - free(data); - return success; -} /* * upb::pb::TextPrinter * @@ -9375,7 +9839,6 @@ bool upb_load_descriptor_file_into_symtab(upb_symtab *symtab, const char *fname, #include <inttypes.h> #include <stdarg.h> #include <stdio.h> -#include <stdlib.h> #include <string.h> @@ -9471,14 +9934,14 @@ bool putf(upb_textprinter *p, const char *fmt, ...) { va_end(args_copy); /* + 1 for NULL terminator (vsprintf() requires it even if we don't). */ - str = malloc(len + 1); + str = upb_gmalloc(len + 1); if (!str) return false; written = vsprintf(str, fmt, args); va_end(args); UPB_ASSERT_VAR(written, written == len); ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL); - free(str); + upb_gfree(str); return ok; } @@ -9847,12 +10310,11 @@ upb_decoderet upb_vdecode_max8_wright(upb_decoderet r) { ** - handling of keys/escape-sequences/etc that span input buffers. */ -#include <stdio.h> -#include <stdint.h> #include <assert.h> -#include <string.h> -#include <stdlib.h> #include <errno.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> #define UPB_JSON_MAX_DEPTH 64 @@ -10975,11 +11437,11 @@ static void end_object(upb_json_parser *p) { * final state once, when the closing '"' is seen. */ -#line 1246 "upb/json/parser.rl" +#line 1245 "upb/json/parser.rl" -#line 1158 "upb/json/parser.c" +#line 1157 "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, @@ -11128,7 +11590,7 @@ static const int json_en_value_machine = 27; static const int json_en_main = 1; -#line 1249 "upb/json/parser.rl" +#line 1248 "upb/json/parser.rl" size_t parse(void *closure, const void *hd, const char *buf, size_t size, const upb_bufhandle *handle) { @@ -11150,7 +11612,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size, capture_resume(parser, buf); -#line 1329 "upb/json/parser.c" +#line 1328 "upb/json/parser.c" { int _klen; unsigned int _trans; @@ -11225,118 +11687,118 @@ _match: switch ( *_acts++ ) { case 0: -#line 1161 "upb/json/parser.rl" +#line 1160 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 1: -#line 1162 "upb/json/parser.rl" +#line 1161 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 10; goto _again;} } break; case 2: -#line 1166 "upb/json/parser.rl" +#line 1165 "upb/json/parser.rl" { start_text(parser, p); } break; case 3: -#line 1167 "upb/json/parser.rl" +#line 1166 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_text(parser, p)); } break; case 4: -#line 1173 "upb/json/parser.rl" +#line 1172 "upb/json/parser.rl" { start_hex(parser); } break; case 5: -#line 1174 "upb/json/parser.rl" +#line 1173 "upb/json/parser.rl" { hexdigit(parser, p); } break; case 6: -#line 1175 "upb/json/parser.rl" +#line 1174 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_hex(parser)); } break; case 7: -#line 1181 "upb/json/parser.rl" +#line 1180 "upb/json/parser.rl" { CHECK_RETURN_TOP(escape(parser, p)); } break; case 8: -#line 1187 "upb/json/parser.rl" +#line 1186 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 9: -#line 1190 "upb/json/parser.rl" +#line 1189 "upb/json/parser.rl" { {stack[top++] = cs; cs = 19; goto _again;} } break; case 10: -#line 1192 "upb/json/parser.rl" +#line 1191 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 27; goto _again;} } break; case 11: -#line 1197 "upb/json/parser.rl" +#line 1196 "upb/json/parser.rl" { start_member(parser); } break; case 12: -#line 1198 "upb/json/parser.rl" +#line 1197 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_membername(parser)); } break; case 13: -#line 1201 "upb/json/parser.rl" +#line 1200 "upb/json/parser.rl" { end_member(parser); } break; case 14: -#line 1207 "upb/json/parser.rl" +#line 1206 "upb/json/parser.rl" { start_object(parser); } break; case 15: -#line 1210 "upb/json/parser.rl" +#line 1209 "upb/json/parser.rl" { end_object(parser); } break; case 16: -#line 1216 "upb/json/parser.rl" +#line 1215 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_array(parser)); } break; case 17: -#line 1220 "upb/json/parser.rl" +#line 1219 "upb/json/parser.rl" { end_array(parser); } break; case 18: -#line 1225 "upb/json/parser.rl" +#line 1224 "upb/json/parser.rl" { start_number(parser, p); } break; case 19: -#line 1226 "upb/json/parser.rl" +#line 1225 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 20: -#line 1228 "upb/json/parser.rl" +#line 1227 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_stringval(parser)); } break; case 21: -#line 1229 "upb/json/parser.rl" +#line 1228 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_stringval(parser)); } break; case 22: -#line 1231 "upb/json/parser.rl" +#line 1230 "upb/json/parser.rl" { CHECK_RETURN_TOP(parser_putbool(parser, true)); } break; case 23: -#line 1233 "upb/json/parser.rl" +#line 1232 "upb/json/parser.rl" { CHECK_RETURN_TOP(parser_putbool(parser, false)); } break; case 24: -#line 1235 "upb/json/parser.rl" +#line 1234 "upb/json/parser.rl" { /* null value */ } break; case 25: -#line 1237 "upb/json/parser.rl" +#line 1236 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_subobject(parser)); } break; case 26: -#line 1238 "upb/json/parser.rl" +#line 1237 "upb/json/parser.rl" { end_subobject(parser); } break; case 27: -#line 1243 "upb/json/parser.rl" +#line 1242 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; -#line 1515 "upb/json/parser.c" +#line 1514 "upb/json/parser.c" } } @@ -11349,10 +11811,10 @@ _again: _out: {} } -#line 1270 "upb/json/parser.rl" +#line 1269 "upb/json/parser.rl" if (p != pe) { - upb_status_seterrf(&parser->status, "Parse error at %s\n", p); + 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); @@ -11390,13 +11852,13 @@ static void json_parser_reset(upb_json_parser *p) { /* Emit Ragel initialization of the parser. */ -#line 1569 "upb/json/parser.c" +#line 1568 "upb/json/parser.c" { cs = json_start; top = 0; } -#line 1310 "upb/json/parser.rl" +#line 1309 "upb/json/parser.rl" p->current_state = cs; p->parser_top = top; accumulate_clear(p); @@ -11422,12 +11884,12 @@ static void free_json_parsermethod(upb_refcounted *r) { upb_value val = upb_inttable_iter_value(&i); upb_strtable *t = upb_value_getptr(val); upb_strtable_uninit(t); - free(t); + upb_gfree(t); } upb_inttable_uninit(&method->name_tables); - free(r); + upb_gfree(r); } static void add_jsonname_table(upb_json_parsermethod *m, const upb_msgdef* md) { @@ -11444,7 +11906,7 @@ static void add_jsonname_table(upb_json_parsermethod *m, const upb_msgdef* md) { } /* TODO(haberman): handle malloc failure. */ - t = malloc(sizeof(*t)); + t = upb_gmalloc(sizeof(*t)); upb_strtable_init(t, UPB_CTYPE_CONSTPTR); upb_inttable_insertptr(&m->name_tables, md, upb_value_ptr(t)); @@ -11452,20 +11914,31 @@ static void add_jsonname_table(upb_json_parsermethod *m, const upb_msgdef* 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) { - buf = realloc(buf, field_len); + size_t len2; + buf = upb_grealloc(buf, 0, field_len); len = field_len; - upb_fielddef_getjsonname(f, buf, len); + len2 = upb_fielddef_getjsonname(f, buf, len); + UPB_ASSERT_VAR(len2, 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)); } } - free(buf); + upb_gfree(buf); } /* Public API *****************************************************************/ @@ -11505,7 +11978,7 @@ 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 = malloc(sizeof(*ret)); + upb_json_parsermethod *ret = upb_gmalloc(sizeof(*ret)); upb_refcounted_init(upb_json_parsermethod_upcast_mutable(ret), &vtbl, owner); ret->msg = md; @@ -11532,8 +12005,6 @@ const upb_byteshandler *upb_json_parsermethod_inputhandler( */ -#include <stdlib.h> -#include <stdio.h> #include <string.h> #include <stdint.h> @@ -11566,20 +12037,26 @@ typedef struct { void freestrpc(void *ptr) { strpc *pc = ptr; - free(pc->ptr); - free(pc); + 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) { +strpc *newstrpc(upb_handlers *h, const upb_fielddef *f, + bool preserve_fieldnames) { /* TODO(haberman): handle malloc failure. */ - strpc *ret = malloc(sizeof(*ret)); - size_t len; - ret->len = upb_fielddef_getjsonname(f, NULL, 0); - ret->ptr = malloc(ret->len); - len = upb_fielddef_getjsonname(f, ret->ptr, ret->len); - UPB_ASSERT_VAR(len, len == ret->len); - ret->len--; /* NULL */ + 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_VAR(len, len == ret->len); + ret->len--; /* NULL */ + } upb_handlers_addcleanup(h, ret, freestrpc); return ret; @@ -12085,11 +12562,12 @@ static size_t mapkey_bytes(void *closure, const void *handler_data, static void set_enum_hd(upb_handlers *h, const upb_fielddef *f, + bool preserve_fieldnames, upb_handlerattr *attr) { - EnumHandlerData *hd = malloc(sizeof(EnumHandlerData)); + EnumHandlerData *hd = upb_gmalloc(sizeof(EnumHandlerData)); hd->enumdef = (const upb_enumdef *)upb_fielddef_subdef(f); - hd->keyname = newstrpc(h, f); - upb_handlers_addcleanup(h, hd, free); + hd->keyname = newstrpc(h, f, preserve_fieldnames); + upb_handlers_addcleanup(h, hd, upb_gfree); upb_handlerattr_sethandlerdata(attr, hd); } @@ -12105,7 +12583,8 @@ static void set_enum_hd(upb_handlers *h, * 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, upb_handlers *h) { +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 @@ -12179,7 +12658,7 @@ void printer_sethandlers_mapentry(const void *closure, upb_handlers *h) { break; case UPB_TYPE_ENUM: { upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER; - set_enum_hd(h, value_field, &enum_attr); + 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; @@ -12198,13 +12677,13 @@ void printer_sethandlers(const void *closure, upb_handlers *h) { bool is_mapentry = upb_msgdef_mapentry(md); upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; upb_msg_field_iter i; - - UPB_UNUSED(closure); + 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, h); + printer_sethandlers_mapentry(closure, preserve_fieldnames, h); return; } @@ -12225,7 +12704,8 @@ void printer_sethandlers(const void *closure, upb_handlers *h) { const upb_fielddef *f = upb_msg_iter_field(&i); upb_handlerattr name_attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&name_attr, newstrpc(h, f)); + upb_handlerattr_sethandlerdata(&name_attr, + newstrpc(h, f, preserve_fieldnames)); if (upb_fielddef_ismap(f)) { upb_handlers_setstartseq(h, f, startmap, &name_attr); @@ -12248,7 +12728,7 @@ void printer_sethandlers(const void *closure, upb_handlers *h) { * 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, &enum_attr); + set_enum_hd(h, f, preserve_fieldnames, &enum_attr); if (upb_fielddef_isseq(f)) { upb_handlers_setint32(h, f, repeated_enum, &enum_attr); @@ -12325,6 +12805,8 @@ 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) { - return upb_handlers_newfrozen(md, owner, printer_sethandlers, NULL); + 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 index 0be5b296..2faf74e5 100644 --- a/ruby/ext/google/protobuf_c/upb.h +++ b/ruby/ext/google/protobuf_c/upb.h @@ -5,6 +5,7 @@ ** ** - 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. @@ -79,6 +80,18 @@ #include <stdbool.h> #include <stddef.h> +#ifdef __cplusplus +namespace upb { +class Allocator; +class Arena; +class Environment; +class ErrorSpace; +class Status; +template <int N> class InlinedArena; +template <int N> class InlinedEnvironment; +} +#endif + /* UPB_INLINE: inline if possible, emit standalone code if required. */ #ifdef __cplusplus #define UPB_INLINE inline @@ -146,6 +159,7 @@ #define UPB_ASSERT_STDLAYOUT(type) \ static_assert(std::is_standard_layout<type>::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&); \ @@ -155,6 +169,7 @@ ~class_name(); \ UPB_DISALLOW_COPY_AND_ASSIGN(class_name) #define UPB_ASSERT_STDLAYOUT(type) +#define UPB_FINAL #endif /* UPB_DECLARE_TYPE() @@ -256,6 +271,7 @@ /* Generic function type. */ typedef void upb_func(); + /* C++ Casts ******************************************************************/ #ifdef __cplusplus @@ -333,243 +349,430 @@ class PointerBase2 : public PointerBase<T, Base> { #endif -/* upb::reffed_ptr ************************************************************/ +/* 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; +}; -#include <algorithm> /* For std::swap(). */ -namespace upb { +/* upb::Status ****************************************************************/ -/* Provides RAII semantics for upb refcounted objects. Each reffed_ptr owns a - * ref on whatever object it points to (if any). */ -template <class T> class reffed_ptr { +/* 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: - reffed_ptr() : ptr_(NULL) {} + Status() { upb_status_clear(this); } - /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */ - template <class U> - reffed_ptr(U* val, const void* ref_donor = NULL) - : ptr_(upb::upcast(val)) { - if (ref_donor) { - assert(ptr_); - ptr_->DonateRef(ref_donor, this); - } else if (ptr_) { - ptr_->Ref(this); - } - } + /* Returns true if there is no error. */ + bool ok() const { return upb_ok(this); } - template <class U> - reffed_ptr(const reffed_ptr<U>& other) - : ptr_(upb::upcast(other.get())) { - if (ptr_) ptr_->Ref(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); } - ~reffed_ptr() { if (ptr_) ptr_->Unref(this); } + /* The returned string is invalidated by any other call into the status. */ + const char *error_message() const { return upb_status_errmsg(this); } - template <class U> - reffed_ptr& operator=(const reffed_ptr<U>& other) { - reset(other.get()); - return *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); } - reffed_ptr& operator=(const reffed_ptr& other) { - reset(other.get()); - return *this; - } + /* Resets the status to a successful state with no message. */ + void Clear() { upb_status_clear(this); } - /* TODO(haberman): add C++11 move construction/assignment for greater - * efficiency. */ + void CopyFrom(const Status& other) { upb_status_copy(this, &other); } - void swap(reffed_ptr& other) { - if (ptr_ == other.ptr_) { - return; - } + private: + UPB_DISALLOW_COPY_AND_ASSIGN(Status) +#else +struct upb_status { +#endif + bool ok_; - if (ptr_) ptr_->DonateRef(this, &other); - if (other.ptr_) other.ptr_->DonateRef(&other, this); - std::swap(ptr_, other.ptr_); - } + /* Specific status code defined by some error space (optional). */ + int code_; + upb_errorspace *error_space_; - T& operator*() const { - assert(ptr_); - return *ptr_; - } + /* TODO(haberman): add file/line of error? */ - T* operator->() const { - assert(ptr_); - return ptr_; - } + /* Error message; NULL-terminated. */ + char msg[UPB_STATUS_MAX_MESSAGE]; +}; - T* get() const { return ptr_; } +#define UPB_STATUS_INIT {true, 0, NULL, {0}} - /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */ - template <class U> - void reset(U* ptr = NULL, const void* ref_donor = NULL) { - reffed_ptr(ptr, ref_donor).swap(*this); - } - template <class U> - reffed_ptr<U> down_cast() { - return reffed_ptr<U>(upb::down_cast<U*>(get())); - } +/** Built-in error spaces. ****************************************************/ - template <class U> - reffed_ptr<U> dyn_cast() { - return reffed_ptr<U>(upb::dyn_cast<U*>(get())); - } +/* 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; - /* 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; - } +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: - T* ptr_; + UPB_DISALLOW_COPY_AND_ASSIGN(Allocator) + + public: +#else +struct upb_alloc { +#endif /* __cplusplus */ + upb_alloc_func *func; }; -} /* namespace upb */ +UPB_INLINE void *upb_malloc(upb_alloc *alloc, size_t size) { + assert(size > 0); + return alloc->func(alloc, NULL, 0, size); +} -#endif /* __cplusplus */ +UPB_INLINE void *upb_realloc(upb_alloc *alloc, void *ptr, size_t oldsize, + size_t size) { + assert(size > 0); + return alloc->func(alloc, ptr, oldsize, size); +} +UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) { + alloc->func(alloc, ptr, 0, 0); +} -/* upb::Status ****************************************************************/ +/* The global allocator used by upb. Uses the standard malloc()/free(). */ -#ifdef __cplusplus -namespace upb { -class ErrorSpace; -class Status; +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); } -#endif -UPB_DECLARE_TYPE(upb::ErrorSpace, upb_errorspace) -UPB_DECLARE_TYPE(upb::Status, upb_status) +UPB_INLINE void *upb_grealloc(void *ptr, size_t oldsize, size_t size) { + return upb_realloc(&upb_alloc_global, ptr, oldsize, size); +} -/* The maximum length of an error message before it will get truncated. */ -#define UPB_STATUS_MAX_MESSAGE 128 +UPB_INLINE void upb_gfree(void *ptr) { + upb_free(&upb_alloc_global, ptr); +} -/* An error callback function is used to report errors from some component. - * The function can return "true" to indicate that the component should try - * to recover and proceed, but this is not always possible. */ -typedef bool upb_errcb_t(void *closure, const upb_status* status); +/* 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); +upb_alloc *upb_arena_alloc(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_END_EXTERN_C #ifdef __cplusplus -class upb::ErrorSpace { + +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_errorspace { -#endif - const char *name; - /* Should the error message in the status object according to this code. */ - void (*set_message)(upb_status* status, int code); +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; }; -#ifdef __cplusplus -/* Object representing a success or failure status. - * It owns no resources and allocates no memory, so it should work - * even in OOM situations. */ +/* upb::Environment ***********************************************************/ -class upb::Status { - public: - Status(); +/* 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) - /* Returns true if there is no error. */ - bool ok() const; +/* 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); - /* Optional error space and code, useful if the caller wants to - * programmatically check the specific kind of error. */ - ErrorSpace* error_space(); - int code() const; +UPB_BEGIN_EXTERN_C - const char *error_message() const; +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); - /* The error message will be truncated if it is longer than - * UPB_STATUS_MAX_MESSAGE-4. */ - void SetErrorMessage(const char* msg); - void SetFormattedErrorMessage(const char* fmt, ...); +void upb_env_initonly(upb_env *e); - /* If there is no error message already, this will use the ErrorSpace to - * populate the error message for this code. The caller can still call - * SetErrorMessage() to give a more specific message. */ - void SetErrorCode(ErrorSpace* space, int code); +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); - /* Resets the status to a successful state with no message. */ - void Clear(); +/* 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); + } - void CopyFrom(const Status& other); + 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(Status) + UPB_DISALLOW_COPY_AND_ASSIGN(Environment) + #else -struct upb_status { -#endif +struct upb_env { +#endif /* __cplusplus */ + upb_arena arena_; + upb_error_func *error_func_; + void *error_ud_; bool ok_; +}; - /* Specific status code defined by some error space (optional). */ - int code_; - upb_errorspace *error_space_; - /* Error message; NULL-terminated. */ - char msg[UPB_STATUS_MAX_MESSAGE]; -}; +/* upb::InlinedArena **********************************************************/ +/* upb::InlinedEnvironment ****************************************************/ -#define UPB_STATUS_INIT {true, 0, NULL, {0}} +/* 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 -extern "C" { -#endif -/* The returned string is invalidated by any other call into the status. */ -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); +template <int N> class upb::InlinedArena : public upb::Arena { + public: + InlinedArena() : Arena(initial_block_, N, NULL) {} + explicit InlinedArena(Allocator* a) : Arena(initial_block_, N, a) {} -/* 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_seterrcode(upb_status *status, upb_errorspace *space, int code); -void upb_status_copy(upb_status *to, const upb_status *from); + private: + UPB_DISALLOW_COPY_AND_ASSIGN(InlinedArena) -#ifdef __cplusplus -} /* extern "C" */ + char initial_block_[N + UPB_ARENA_BLOCK_OVERHEAD]; +}; -namespace upb { +template <int N> class upb::InlinedEnvironment : public upb::Environment { + public: + InlinedEnvironment() : Environment(initial_block_, N, NULL) {} + explicit InlinedEnvironment(Allocator *a) + : Environment(initial_block_, N, a) {} -/* C++ Wrappers */ -inline Status::Status() { Clear(); } -inline bool Status::ok() const { return upb_ok(this); } -inline const char* Status::error_message() const { - return upb_status_errmsg(this); -} -inline void Status::SetErrorMessage(const char* msg) { - upb_status_seterrmsg(this, msg); -} -inline void Status::SetFormattedErrorMessage(const char* fmt, ...) { - va_list args; - va_start(args, fmt); - upb_status_vseterrf(this, fmt, args); - va_end(args); -} -inline void Status::SetErrorCode(ErrorSpace* space, int code) { - upb_status_seterrcode(this, space, code); -} -inline void Status::Clear() { upb_status_clear(this); } -inline void Status::CopyFrom(const Status& other) { - upb_status_copy(this, &other); -} + private: + UPB_DISALLOW_COPY_AND_ASSIGN(InlinedEnvironment) + + char initial_block_[N + UPB_ARENA_BLOCK_OVERHEAD]; +}; + +#endif /* __cplusplus */ -} /* namespace upb */ -#endif #endif /* UPB_H_ */ @@ -611,10 +814,14 @@ typedef struct { #endif /* Like strdup(), which isn't always available since it's not ANSI C. */ -char *upb_strdup(const char *s); +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); +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) { @@ -791,14 +998,40 @@ typedef struct { * 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) \ - {{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) @@ -811,7 +1044,7 @@ typedef struct { } upb_inttable; #define UPB_INTTABLE_INIT(count, mask, ctype, size_lg2, ent, a, asize, acount) \ - {{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) @@ -851,10 +1084,26 @@ UPB_INLINE bool upb_arrhas(upb_tabval key) { /* Initialize and uninitialize a table, respectively. If memory allocation * failed, false is returned that the table is uninitialized. */ -bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype); -bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype); -void upb_inttable_uninit(upb_inttable *table); -void upb_strtable_uninit(upb_strtable *table); +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); @@ -869,9 +1118,20 @@ UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) { * * If a table resize was required but memory allocation failed, false is * returned and the table is unchanged. */ -bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val); -bool upb_strtable_insert2(upb_strtable *t, const char *key, size_t len, - upb_value val); +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, @@ -894,8 +1154,13 @@ UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key, /* 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_remove2(upb_strtable *t, const char *key, size_t len, - 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, @@ -910,19 +1175,33 @@ 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_push(upb_inttable *t, upb_value val); +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_insertptr(upb_inttable *t, const void *key, upb_value val); +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_compact(upb_inttable *t); +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. */ @@ -951,7 +1230,7 @@ UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key, } /* Exposed for testing only. */ -bool upb_strtable_resize(upb_strtable *t, size_t size_lg2); +bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a); /* Iterators ******************************************************************/ @@ -996,8 +1275,8 @@ typedef struct { 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(upb_strtable_iter *i); -size_t upb_strtable_iter_keylength(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, @@ -1050,7 +1329,10 @@ bool upb_inttable_iter_isequal(const upb_inttable_iter *i1, /* #define UPB_DEBUG_REFS */ #ifdef __cplusplus -namespace upb { class RefCounted; } +namespace upb { +class RefCounted; +template <class T> class reffed_ptr; +} #endif UPB_DECLARE_TYPE(upb::RefCounted, upb_refcounted) @@ -1118,10 +1400,12 @@ struct upb_refcounted { }; #ifdef UPB_DEBUG_REFS -#define UPB_REFCOUNT_INIT(refs, ref2s) \ - {&static_refcount, NULL, NULL, 0, true, refs, ref2s} +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(refs, ref2s) {&static_refcount, NULL, NULL, 0, true} +#define UPB_REFCOUNT_INIT(vtbl, refs, ref2s) \ + {&static_refcount, NULL, vtbl, 0, true} #endif UPB_BEGIN_EXTERN_C @@ -1254,6 +1538,111 @@ inline void RefCounted::CheckRef(const void *owner) const { } /* namespace upb */ #endif + +/* upb::reffed_ptr ************************************************************/ + +#ifdef __cplusplus + +#include <algorithm> /* 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 T> class upb::reffed_ptr { + public: + reffed_ptr() : ptr_(NULL) {} + + /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */ + template <class U> + reffed_ptr(U* val, const void* ref_donor = NULL) + : ptr_(upb::upcast(val)) { + if (ref_donor) { + assert(ptr_); + ptr_->DonateRef(ref_donor, this); + } else if (ptr_) { + ptr_->Ref(this); + } + } + + template <class U> + reffed_ptr(const reffed_ptr<U>& 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 <class U> + reffed_ptr& operator=(const reffed_ptr<U>& 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 { + assert(ptr_); + return *ptr_; + } + + T* operator->() const { + assert(ptr_); + return ptr_; + } + + T* get() const { return ptr_; } + + /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */ + template <class U> + void reset(U* ptr = NULL, const void* ref_donor = NULL) { + reffed_ptr(ptr, ref_donor).swap(*this); + } + + template <class U> + reffed_ptr<U> down_cast() { + return reffed_ptr<U>(upb::down_cast<U*>(get())); + } + + template <class U> + reffed_ptr<U> dyn_cast() { + return reffed_ptr<U>(upb::dyn_cast<U*>(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 @@ -1265,12 +1654,17 @@ namespace upb { class Def; class EnumDef; class FieldDef; +class FileDef; class MessageDef; class OneofDef; } #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) /* 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 @@ -1282,15 +1676,16 @@ UPB_DECLARE_DERIVED_TYPE(upb::Def, upb::RefCounted, upb_def, upb_refcounted) #define UPB_MAX_MESSAGE_DEPTH 64 -/* upb::Def: base class for defs *********************************************/ +/* upb::Def: base class for top-level defs ***********************************/ -/* All the different kind of defs we support. These correspond 1:1 with - * declarations in a .proto file. */ +/* 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_ONEOF, UPB_DEF_SERVICE, /* Not yet implemented. */ UPB_DEF_ANY = -1 /* Wildcard for upb_symtab_get*() */ } upb_deftype_t; @@ -1313,6 +1708,9 @@ class upb::Def { /* "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" @@ -1320,6 +1718,11 @@ class upb::Def { 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. @@ -1331,7 +1734,7 @@ class upb::Def { * * After this operation succeeds, the finalized defs must only be accessed * through a const pointer! */ - static bool Freeze(Def* const* defs, int n, Status* status); + static bool Freeze(Def* const* defs, size_t n, Status* status); static bool Freeze(const std::vector<Def*>& defs, Status* status); private: @@ -1350,8 +1753,13 @@ 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, int n, 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 @@ -1424,7 +1832,6 @@ UPB_END_EXTERN_C UPB_DECLARE_DEF_TYPE(upb::FieldDef, fielddef, FIELD) UPB_DECLARE_DEF_TYPE(upb::MessageDef, msgdef, MSG) UPB_DECLARE_DEF_TYPE(upb::EnumDef, enumdef, ENUM) -UPB_DECLARE_DEF_TYPE(upb::OneofDef, oneofdef, ONEOF) #undef UPB_DECLARE_DEF_TYPE #undef UPB_DEF_CASTS @@ -1487,6 +1894,11 @@ typedef enum { 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) @@ -1582,7 +1994,7 @@ class upb::FieldDef { * 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. */ - int index() const; + uint32_t index() const; /* The MessageDef to which this field belongs. * @@ -1878,6 +2290,10 @@ UPB_END_EXTERN_C 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. @@ -1893,6 +2309,7 @@ class upb::MessageDef { /* 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); @@ -1935,6 +2352,11 @@ class upb::MessageDef { bool AddOneof(OneofDef* o, Status* s); bool AddOneof(const reffed_ptr<OneofDef>& 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. */ @@ -2125,15 +2547,20 @@ UPB_REFCOUNTED_CMETHODS(upb_msgdef, upb_msgdef_upcast2) bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status); +upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner); const char *upb_msgdef_fullname(const upb_msgdef *m); -bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, upb_status *s); +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); -upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner); 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); -void upb_msgdef_setprimitiveshavepresence(upb_msgdef *m, bool have_presence); +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 @@ -2175,18 +2602,21 @@ UPB_INLINE upb_oneofdef *upb_msgdef_ntoo_mutable(upb_msgdef *m, return (upb_oneofdef *)upb_msgdef_ntoo(m, name, len); } -void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry); -bool upb_msgdef_mapentry(const upb_msgdef *m); - -/* Well-known field tag numbers for map-entry messages. */ -#define UPB_MAPENTRY_KEY 1 -#define UPB_MAPENTRY_VALUE 2 +/* 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); -const upb_oneofdef *upb_msgdef_findoneof(const upb_msgdef *m, - const char *name); -int upb_msgdef_numoneofs(const upb_msgdef *m); +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); +} -/* upb_msg_field_iter i; +/* 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)) { @@ -2232,6 +2662,7 @@ class upb::EnumDef { /* 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); @@ -2306,6 +2737,7 @@ 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); @@ -2347,8 +2779,7 @@ typedef upb_inttable_iter upb_oneof_iter; #ifdef __cplusplus -/* Class that represents a oneof. Its base class is upb::Def (convert with - * upb::upcast()). */ +/* Class that represents a oneof. */ class upb::OneofDef { public: /* Returns NULL if memory allocation failed. */ @@ -2357,9 +2788,6 @@ class upb::OneofDef { /* upb::RefCounted methods like Ref()/Unref(). */ UPB_REFCOUNTED_CPPMETHODS - /* Functionality from upb::Def. */ - const char* full_name() const; - /* Returns the MessageDef that owns this OneofDef. */ const MessageDef* containing_type() const; @@ -2367,6 +2795,7 @@ class upb::OneofDef { * 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; @@ -2460,7 +2889,7 @@ upb_oneofdef *upb_oneofdef_new(const void *owner); upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner); /* Include upb_refcounted methods like upb_oneofdef_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_oneofdef, upb_oneofdef_upcast2) +UPB_REFCOUNTED_CMETHODS(upb_oneofdef, upb_oneofdef_upcast) const char *upb_oneofdef_name(const upb_oneofdef *o); bool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s); @@ -2496,6 +2925,120 @@ 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<FileDef> 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); + + /* 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); +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_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 + #ifdef __cplusplus UPB_INLINE const char* upb_safecstr(const std::string& str) { @@ -2511,13 +3054,14 @@ inline Def* Def::Dup(const void* owner) const { } 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, int n, Status* status) { +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<Def*>& defs, Status* status) { @@ -2596,6 +3140,9 @@ inline void FieldDef::set_lazy(bool 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); } @@ -2740,12 +3287,21 @@ inline reffed_ptr<MessageDef> MessageDef::New() { 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); } @@ -2927,6 +3483,9 @@ inline reffed_ptr<EnumDef> EnumDef::New() { 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); } @@ -2976,9 +3535,6 @@ inline reffed_ptr<OneofDef> OneofDef::New() { upb_oneofdef *o = upb_oneofdef_new(&o); return reffed_ptr<OneofDef>(o, &o); } -inline const char* OneofDef::full_name() const { - return upb_oneofdef_name(this); -} inline const MessageDef* OneofDef::containing_type() const { return upb_oneofdef_containingtype(this); @@ -2989,6 +3545,9 @@ inline const char* OneofDef::name() const { 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); } @@ -3057,6 +3616,57 @@ inline bool OneofDef::const_iterator::operator!=( return !(*this == other); } +inline reffed_ptr<FileDef> FileDef::New() { + upb_filedef *f = upb_filedef_new(&f); + return reffed_ptr<FileDef>(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 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<Def*>(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 @@ -3095,6 +3705,7 @@ 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 @@ -3104,8 +3715,8 @@ struct upb_def { bool came_from_user; }; -#define UPB_DEF_INIT(name, type, refs, ref2s) \ - { UPB_REFCOUNT_INIT(refs, ref2s), name, type, false } +#define UPB_DEF_INIT(name, type, vtbl, refs, ref2s) \ + { UPB_REFCOUNT_INIT(vtbl, refs, ref2s), name, NULL, type, false } /* upb_fielddef ***************************************************************/ @@ -3145,12 +3756,14 @@ struct upb_fielddef { 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, refs, ref2s), defaultval, {msgdef}, \ - {subdef}, NULL, false, false, \ + 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 \ } @@ -3166,32 +3779,26 @@ struct upb_msgdef { /* Tables for looking up fields by number and name. */ upb_inttable itof; /* int to field */ - upb_strtable ntof; /* name to field */ + upb_strtable ntof; /* name to field/oneof */ - /* Tables for looking up oneofs by name. */ - upb_strtable ntoo; /* name to oneof */ - - /* Is this a map-entry message? - * TODO: set this flag properly for static descriptors; regenerate - * descriptor.upb.c. */ + /* Is this a map-entry message? */ bool map_entry; - /* Do primitive values in this message have explicit presence or not? - * TODO: set this flag properly for static descriptors; regenerate - * descriptor.upb.c. */ - bool primitives_have_presence; + /* 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, \ - refs, ref2s) \ + map_entry, syntax, refs, ref2s) \ { \ - UPB_DEF_INIT(name, UPB_DEF_MSG, refs, ref2s), selector_count, \ - submsg_field_count, itof, ntof, \ - UPB_EMPTY_STRTABLE_INIT(UPB_CTYPE_PTR), false, true \ + UPB_DEF_INIT(name, UPB_DEF_MSG, &upb_fielddef_vtbl, refs, ref2s), \ + selector_count, submsg_field_count, itof, ntof, map_entry, syntax \ } @@ -3205,22 +3812,28 @@ struct upb_enumdef { 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, refs, ref2s), ntoi, iton, defaultval } + { UPB_DEF_INIT(name, UPB_DEF_ENUM, &upb_enumdef_vtbl, refs, ref2s), ntoi, \ + iton, defaultval } /* upb_oneofdef ***************************************************************/ struct upb_oneofdef { - upb_def base; + upb_refcounted base; + 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_DEF_INIT(name, UPB_DEF_ENUM, refs, ref2s), ntof, itof } + { UPB_REFCOUNT_INIT(&upb_oneofdef_vtbl, refs, ref2s), name, ntof, itof } /* upb_symtab *****************************************************************/ @@ -3231,9 +3844,18 @@ struct upb_symtab { upb_strtable symtab; }; -#define UPB_SYMTAB_INIT(symtab, refs, ref2s) \ - { UPB_REFCOUNT_INIT(refs, ref2s), symtab } +struct upb_filedef { + upb_refcounted base; + const char *name; + const char *package; + upb_syntax_t syntax; + + upb_inttable defs; + upb_inttable deps; +}; + +extern const struct upb_refcounted_vtbl upb_filedef_vtbl; #endif /* UPB_STATICINIT_H_ */ /* @@ -5176,267 +5798,6 @@ inline BytesHandler::~BytesHandler() {} #endif /* UPB_HANDLERS_H */ /* -** upb::Environment (upb_env) -** -** 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. -*/ - - -#ifndef UPB_ENV_H_ -#define UPB_ENV_H_ - -#ifdef __cplusplus -namespace upb { -class Environment; -class SeededAllocator; -} -#endif - -UPB_DECLARE_TYPE(upb::Environment, upb_env) -UPB_DECLARE_TYPE(upb::SeededAllocator, upb_seededalloc) - -typedef void *upb_alloc_func(void *ud, void *ptr, size_t oldsize, size_t size); -typedef void upb_cleanup_func(void *ud); -typedef bool upb_error_func(void *ud, const upb_status *status); - -#ifdef __cplusplus - -/* An environment is *not* thread-safe. */ -class upb::Environment { - public: - Environment(); - ~Environment(); - - /* Set a custom memory allocation function for the environment. May ONLY - * be called before any calls to Malloc()/Realloc()/AddCleanup() below. - * If this is not called, the system realloc() function will be used. - * The given user pointer "ud" will be passed to the allocation function. - * - * The allocation function will not receive corresponding "free" calls. it - * must ensure that the memory is valid for the lifetime of the Environment, - * but it may be reclaimed any time thereafter. The likely usage is that - * "ud" points to a stateful allocator, and that the allocator frees all - * memory, arena-style, when it is destroyed. In this case the allocator must - * outlive the Environment. Another possibility is that the allocation - * function returns GC-able memory that is guaranteed to be GC-rooted for the - * life of the Environment. */ - void SetAllocationFunction(upb_alloc_func* alloc, void* ud); - - template<class T> - void SetAllocator(T* allocator) { - SetAllocationFunction(allocator->GetAllocationFunction(), allocator); - } - - /* Set a custom error reporting function. */ - void SetErrorFunction(upb_error_func* func, void* ud); - - /* Set the error reporting function to simply copy the status to the given - * status and abort. */ - void ReportErrorsTo(Status* 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; - - /* Functions for use by encoders/decoders. **********************************/ - - /* Reports an error to this environment's callback, returning true if - * the caller should try to recover. */ - bool ReportError(const Status* status); - - /* Allocate memory. Uses the environment's allocation function. - * - * There is no need to free(). All memory will be freed automatically, but is - * guaranteed to outlive the Environment. */ - void* Malloc(size_t size); - - /* Reallocate memory. Preserves "oldsize" bytes from the existing buffer - * Requires: oldsize <= existing_size. - * - * TODO(haberman): should we also enforce that oldsize <= size? */ - void* Realloc(void* ptr, size_t oldsize, size_t size); - - /* Add a cleanup function to run when the environment is destroyed. - * Returns false on out-of-memory. - * - * The first call to AddCleanup() after SetAllocationFunction() is guaranteed - * to return true -- this makes it possible to robustly set a cleanup handler - * for a custom allocation function. */ - bool AddCleanup(upb_cleanup_func* func, void* ud); - - /* Total number of bytes that have been allocated. It is undefined what - * Realloc() does to this counter. */ - size_t BytesAllocated() const; - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(Environment) - -#else -struct upb_env { -#endif /* __cplusplus */ - - bool ok_; - size_t bytes_allocated; - - /* Alloc function. */ - upb_alloc_func *alloc; - void *alloc_ud; - - /* Error-reporting function. */ - upb_error_func *err; - void *err_ud; - - /* Userdata for default alloc func. */ - void *default_alloc_ud; - - /* 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_BEGIN_EXTERN_C - -void upb_env_init(upb_env *e); -void upb_env_uninit(upb_env *e); -void upb_env_setallocfunc(upb_env *e, upb_alloc_func *func, void *ud); -void upb_env_seterrorfunc(upb_env *e, upb_error_func *func, void *ud); -void upb_env_reporterrorsto(upb_env *e, upb_status *status); -bool upb_env_ok(const upb_env *e); -bool upb_env_reporterror(upb_env *e, const upb_status *status); -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); -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 - -/* An allocator that allocates from an initial memory region (likely the stack) - * before falling back to another allocator. */ -class upb::SeededAllocator { - public: - SeededAllocator(void *mem, size_t len); - ~SeededAllocator(); - - /* Set a custom fallback memory allocation function for the allocator, to use - * once the initial region runs out. - * - * May ONLY be called before GetAllocationFunction(). If this is not - * called, the system realloc() will be the fallback allocator. */ - void SetFallbackAllocator(upb_alloc_func *alloc, void *ud); - - /* Gets the allocation function for this allocator. */ - upb_alloc_func* GetAllocationFunction(); - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(SeededAllocator) - -#else -struct upb_seededalloc { -#endif /* __cplusplus */ - - /* Fallback alloc function. */ - upb_alloc_func *alloc; - upb_cleanup_func *alloc_cleanup; - void *alloc_ud; - bool need_cleanup; - bool returned_allocfunc; - - /* Userdata for default alloc func. */ - void *default_alloc_ud; - - /* Pointers for the initial memory region. */ - char *mem_base; - char *mem_ptr; - char *mem_limit; - - /* For future expansion, since the size of this struct is exposed to users. */ - void *future1; - void *future2; -}; - -UPB_BEGIN_EXTERN_C - -void upb_seededalloc_init(upb_seededalloc *a, void *mem, size_t len); -void upb_seededalloc_uninit(upb_seededalloc *a); -void upb_seededalloc_setfallbackalloc(upb_seededalloc *a, upb_alloc_func *func, - void *ud); -upb_alloc_func *upb_seededalloc_getallocfunc(upb_seededalloc *a); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { - -inline Environment::Environment() { - upb_env_init(this); -} -inline Environment::~Environment() { - upb_env_uninit(this); -} -inline void Environment::SetAllocationFunction(upb_alloc_func *alloc, - void *ud) { - upb_env_setallocfunc(this, alloc, ud); -} -inline void Environment::SetErrorFunction(upb_error_func *func, void *ud) { - upb_env_seterrorfunc(this, func, ud); -} -inline void Environment::ReportErrorsTo(Status* status) { - upb_env_reporterrorsto(this, status); -} -inline bool Environment::ok() const { - return upb_env_ok(this); -} -inline bool Environment::ReportError(const Status* status) { - return upb_env_reporterror(this, status); -} -inline void *Environment::Malloc(size_t size) { - return upb_env_malloc(this, size); -} -inline void *Environment::Realloc(void *ptr, size_t oldsize, size_t size) { - return upb_env_realloc(this, ptr, oldsize, size); -} -inline bool Environment::AddCleanup(upb_cleanup_func *func, void *ud) { - return upb_env_addcleanup(this, func, ud); -} -inline size_t Environment::BytesAllocated() const { - return upb_env_bytesallocated(this); -} - -inline SeededAllocator::SeededAllocator(void *mem, size_t len) { - upb_seededalloc_init(this, mem, len); -} -inline SeededAllocator::~SeededAllocator() { - upb_seededalloc_uninit(this); -} -inline void SeededAllocator::SetFallbackAllocator(upb_alloc_func *alloc, - void *ud) { - upb_seededalloc_setfallbackalloc(this, alloc, ud); -} -inline upb_alloc_func *SeededAllocator::GetAllocationFunction() { - return upb_seededalloc_getallocfunc(this); -} - -} /* namespace upb */ - -#endif /* __cplusplus */ - -#endif /* UPB_ENV_H_ */ -/* ** upb::Sink (upb_sink) ** upb::BytesSink (upb_bytessink) ** @@ -6140,12 +6501,17 @@ class upb::SymbolTable { * only a few messages are changing. We may want to add a way of adding a * tree of frozen defs to the symtab (perhaps an alternate constructor where * you pass the root of the tree?) */ - bool Add(Def*const* defs, int n, void* ref_donor, upb_status* status); + bool Add(Def*const* defs, size_t n, void* ref_donor, Status* status); bool Add(const std::vector<Def*>& 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) }; @@ -6166,8 +6532,9 @@ const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base, 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, int n, void *ref_donor, - upb_status *status); +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); @@ -6209,9 +6576,12 @@ inline const MessageDef *SymbolTable::LookupMessage(const char *sym) const { return upb_symtab_lookupmsg(this, sym); } inline bool SymbolTable::Add( - Def*const* defs, int n, void* ref_donor, upb_status* status) { + 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 @@ -6255,14 +6625,9 @@ class upb::descriptor::Reader { /* The reader's input; this is where descriptor.proto data should be sent. */ Sink* input(); - /* Returns an array of all defs that have been parsed, and transfers ownership - * of them to "owner". The number of defs is stored in *n. Ownership of the - * returned array is retained and is invalidated by any other call into - * Reader. - * - * These defs are not frozen or resolved; they are ready to be added to a - * symtab. */ - upb::Def** GetDefs(void* owner, int* n); + /* 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); @@ -6278,7 +6643,8 @@ 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); -upb_def **upb_descreader_getdefs(upb_descreader *r, void *owner, int *n); +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 @@ -6291,8 +6657,11 @@ 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 upb::Def** Reader::GetDefs(void* owner, int* n) { - return upb_descreader_getdefs(this, owner, n); +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 */ @@ -6305,614 +6674,290 @@ inline upb::Def** Reader::GetDefs(void* owner, int* n) { * actually storing protobufs. It only contains *defs* which * let you reflect over a protobuf *schema*. */ -/* This file was generated by upbc (the upb compiler). +/* 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 GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_ -#define GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_ +#ifndef UPB_DESCRIPTOR_DESCRIPTOR_PROTO_UPB_H_ +#define UPB_DESCRIPTOR_DESCRIPTOR_PROTO_UPB_H_ -#ifdef __cplusplus UPB_BEGIN_EXTERN_C -#endif /* 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_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_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_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_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_SPEED = 1, + google_protobuf_FileOptions_CODE_SIZE = 2, + google_protobuf_FileOptions_LITE_RUNTIME = 3 } google_protobuf_FileOptions_OptimizeMode; -/* Selectors */ - -/* google.protobuf.DescriptorProto */ -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSUBMSG 3 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 4 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSUBMSG 6 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_STARTSUBMSG 7 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ONEOF_DECL_STARTSUBMSG 8 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_RESERVED_RANGE_STARTSUBMSG 9 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSEQ 10 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSEQ 11 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSUBMSG 12 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSEQ 13 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSEQ 14 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSUBMSG 15 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 16 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 17 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 18 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSEQ 19 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSEQ 20 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSUBMSG 21 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSEQ 22 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSEQ 23 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSUBMSG 24 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_ENDSUBMSG 25 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ONEOF_DECL_STARTSEQ 26 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ONEOF_DECL_ENDSEQ 27 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ONEOF_DECL_ENDSUBMSG 28 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_RESERVED_RANGE_STARTSEQ 29 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_RESERVED_RANGE_ENDSEQ 30 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_RESERVED_RANGE_ENDSUBMSG 31 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_STRING 32 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_STARTSTR 33 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_ENDSTR 34 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_RESERVED_NAME_STARTSEQ 35 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_RESERVED_NAME_ENDSEQ 36 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_RESERVED_NAME_STRING 37 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_RESERVED_NAME_STARTSTR 38 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_RESERVED_NAME_ENDSTR 39 - -/* google.protobuf.DescriptorProto.ExtensionRange */ -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START_INT32 2 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END_INT32 3 - -/* google.protobuf.DescriptorProto.ReservedRange */ -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_RESERVEDRANGE_START_INT32 2 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_RESERVEDRANGE_END_INT32 3 - -/* google.protobuf.EnumDescriptorProto */ -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 3 -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSEQ 4 -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSEQ 5 -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSUBMSG 6 -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 7 -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_STRING 8 -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_STARTSTR 9 -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_ENDSTR 10 - -/* google.protobuf.EnumOptions */ -#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_ALLOW_ALIAS_BOOL 6 -#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_DEPRECATED_BOOL 7 - -/* google.protobuf.EnumValueDescriptorProto */ -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_STRING 4 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_STARTSTR 5 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_ENDSTR 6 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER_INT32 7 - -/* google.protobuf.EnumValueOptions */ -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_DEPRECATED_BOOL 6 - -/* google.protobuf.FieldDescriptorProto */ -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_STRING 4 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_STARTSTR 5 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_ENDSTR 6 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STRING 7 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STARTSTR 8 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_ENDSTR 9 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_INT32 10 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_INT32 11 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 12 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STRING 13 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STARTSTR 14 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_ENDSTR 15 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STRING 16 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STARTSTR 17 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_ENDSTR 18 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_ONEOF_INDEX_INT32 19 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_JSON_NAME_STRING 20 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_JSON_NAME_STARTSTR 21 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_JSON_NAME_ENDSTR 22 - -/* google.protobuf.FieldOptions */ -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE_INT32 6 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED_BOOL 7 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED_BOOL 8 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_LAZY_BOOL 9 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_JSTYPE_INT32 10 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_WEAK_BOOL 11 - -/* google.protobuf.FileDescriptorProto */ -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 3 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSUBMSG 4 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 6 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_STARTSUBMSG 7 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSEQ 8 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSEQ 9 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSUBMSG 10 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 11 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 12 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 13 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSEQ 14 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSEQ 15 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSUBMSG 16 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSEQ 17 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSEQ 18 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSUBMSG 19 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 20 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_ENDSUBMSG 21 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_STRING 22 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_STARTSTR 23 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_ENDSTR 24 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_STRING 25 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_STARTSTR 26 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_ENDSTR 27 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSEQ 28 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSEQ 29 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STRING 30 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSTR 31 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSTR 32 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_STARTSEQ 33 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_ENDSEQ 34 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_INT32 35 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_STARTSEQ 36 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_ENDSEQ 37 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_INT32 38 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SYNTAX_STRING 39 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SYNTAX_STARTSTR 40 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SYNTAX_ENDSTR 41 - -/* google.protobuf.FileDescriptorSet */ -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSUBMSG 5 - -/* google.protobuf.FileOptions */ -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STRING 6 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STARTSTR 7 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_ENDSTR 8 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STRING 9 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STARTSTR 10 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_ENDSTR 11 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR_INT32 12 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES_BOOL 13 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_STRING 14 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_STARTSTR 15 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_ENDSTR 16 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES_BOOL 17 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES_BOOL 18 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES_BOOL 19 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH_BOOL 20 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_DEPRECATED_BOOL 21 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_STRING_CHECK_UTF8_BOOL 22 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_CC_ENABLE_ARENAS_BOOL 23 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_OBJC_CLASS_PREFIX_STRING 24 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_OBJC_CLASS_PREFIX_STARTSTR 25 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_OBJC_CLASS_PREFIX_ENDSTR 26 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_CSHARP_NAMESPACE_STRING 27 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_CSHARP_NAMESPACE_STARTSTR 28 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_CSHARP_NAMESPACE_ENDSTR 29 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVANANO_USE_DEPRECATED_PACKAGE_BOOL 30 - -/* google.protobuf.MessageOptions */ -#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT_BOOL 6 -#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR_BOOL 7 -#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_DEPRECATED_BOOL 8 -#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_MAP_ENTRY_BOOL 9 - -/* google.protobuf.MethodDescriptorProto */ -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_STRING 4 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_STARTSTR 5 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_ENDSTR 6 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STRING 7 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STARTSTR 8 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_ENDSTR 9 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_STRING 10 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_STARTSTR 11 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_ENDSTR 12 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_CLIENT_STREAMING_BOOL 13 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_SERVER_STREAMING_BOOL 14 - -/* google.protobuf.MethodOptions */ -#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_DEPRECATED_BOOL 6 - -/* google.protobuf.OneofDescriptorProto */ -#define SEL_GOOGLE_PROTOBUF_ONEOFDESCRIPTORPROTO_NAME_STRING 2 -#define SEL_GOOGLE_PROTOBUF_ONEOFDESCRIPTORPROTO_NAME_STARTSTR 3 -#define SEL_GOOGLE_PROTOBUF_ONEOFDESCRIPTORPROTO_NAME_ENDSTR 4 - -/* google.protobuf.ServiceDescriptorProto */ -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 3 -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSEQ 4 -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSEQ 5 -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSUBMSG 6 -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 7 -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_STRING 8 -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_STARTSTR 9 -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_ENDSTR 10 - -/* google.protobuf.ServiceOptions */ -#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_DEPRECATED_BOOL 6 - -/* google.protobuf.SourceCodeInfo */ -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSUBMSG 5 - -/* google.protobuf.SourceCodeInfo.Location */ -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_STARTSEQ 2 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_ENDSEQ 3 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_INT32 4 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_STARTSEQ 5 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_ENDSEQ 6 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_INT32 7 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_STRING 8 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_STARTSTR 9 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_ENDSTR 10 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_STRING 11 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_STARTSTR 12 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_ENDSTR 13 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_DETACHED_COMMENTS_STARTSEQ 14 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_DETACHED_COMMENTS_ENDSEQ 15 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_DETACHED_COMMENTS_STRING 16 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_DETACHED_COMMENTS_STARTSTR 17 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_DETACHED_COMMENTS_ENDSTR 18 - -/* google.protobuf.UninterpretedOption */ -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STRING 6 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STARTSTR 7 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_ENDSTR 8 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE_UINT64 9 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE_INT64 10 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE_DOUBLE 11 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STRING 12 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STARTSTR 13 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_ENDSTR 14 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STRING 15 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STARTSTR 16 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_ENDSTR 17 - -/* google.protobuf.UninterpretedOption.NamePart */ -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STRING 2 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STARTSTR 3 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_ENDSTR 4 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION_BOOL 5 - -const upb_symtab *upbdefs_google_protobuf_descriptor(const void *owner); - -/* MessageDefs */ -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_DescriptorProto(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto.ExtensionRange"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ReservedRange(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto.ReservedRange"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumDescriptorProto(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumDescriptorProto"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumOptions(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumOptions"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumValueDescriptorProto(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumValueDescriptorProto"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumValueOptions(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumValueOptions"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FieldDescriptorProto(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FieldDescriptorProto"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FieldOptions(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FieldOptions"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileDescriptorProto(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorProto"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileDescriptorSet(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorSet"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileOptions(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileOptions"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MessageOptions(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MessageOptions"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MethodDescriptorProto(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MethodDescriptorProto"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MethodOptions(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MethodOptions"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_OneofDescriptorProto(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.OneofDescriptorProto"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_ServiceDescriptorProto(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.ServiceDescriptorProto"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_ServiceOptions(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.ServiceOptions"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_Location(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo.Location"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_NamePart(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption.NamePart"); - assert(m); - return m; -} - - -/* EnumDefs */ -UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Label(const upb_symtab *s) { - const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldDescriptorProto.Label"); - assert(e); - return e; -} -UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Type(const upb_symtab *s) { - const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldDescriptorProto.Type"); - assert(e); - return e; -} -UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldOptions_CType(const upb_symtab *s) { - const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldOptions.CType"); - assert(e); - return e; -} -UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldOptions_JSType(const upb_symtab *s) { - const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldOptions.JSType"); - assert(e); - return e; -} -UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FileOptions_OptimizeMode(const upb_symtab *s) { - const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FileOptions.OptimizeMode"); - assert(e); - return e; -} - -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_end(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto_ExtensionRange(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_start(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto_ExtensionRange(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_end(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto_ReservedRange(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_start(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto_ReservedRange(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_enum_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_extension_range(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_field(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_nested_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_oneof_decl(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 7); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_reserved_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_reserved_range(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 9); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_allow_alias(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumOptions(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_deprecated(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumOptions(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumOptions(s), 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_number(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueOptions_deprecated(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueOptions(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueOptions(s), 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_default_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 7); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_extendee(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_json_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_label(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_number(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_oneof_index(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 9); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_type_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_ctype(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_deprecated(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_jstype(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_lazy(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_packed(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_weak(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_enum_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 7); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_message_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_public_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_service(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_source_code_info(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 9); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_syntax(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 12); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_weak_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 11); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorSet_file(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorSet(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_cc_enable_arenas(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 31); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_cc_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 16); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_csharp_namespace(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 37); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_deprecated(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 23); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_go_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 11); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_generate_equals_and_hash(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 20); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 17); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_multiple_files(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_outer_classname(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_string_check_utf8(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 27); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_javanano_use_deprecated_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 38); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_objc_class_prefix(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 36); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_optimize_for(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 9); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_py_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 18); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_deprecated(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_map_entry(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 7); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_message_set_wire_format(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_no_standard_descriptor_accessor(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_client_streaming(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_input_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_output_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_server_streaming(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodOptions_deprecated(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodOptions(s), 33); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodOptions(s), 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_OneofDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_OneofDescriptorProto(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_method(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceOptions_deprecated(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceOptions(s), 33); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceOptions(s), 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_leading_comments(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_path(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_span(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_trailing_comments(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_location(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_is_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption_NamePart(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_name_part(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption_NamePart(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_aggregate_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_double_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_identifier_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_negative_int_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_positive_int_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_string_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 7); } +/* 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { assert(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 9); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_py_generic_services(const upb_msgdef *m) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { assert(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 7); } UPB_END_EXTERN_C @@ -6921,320 +6966,360 @@ UPB_END_EXTERN_C namespace upbdefs { namespace google { namespace protobuf { -namespace descriptor { -inline upb::reffed_ptr<const upb::SymbolTable> SymbolTable() { - const upb::SymbolTable* s = upbdefs_google_protobuf_descriptor(&s); - return upb::reffed_ptr<const upb::SymbolTable>(s, &s); -} -} /* namespace descriptor */ -} /* namespace protobuf */ -} /* namespace google */ -#define RETURN_REFFED(type, func) \ - const type* obj = func(upbdefs::google::protobuf::descriptor::SymbolTable().get()); \ - return upb::reffed_ptr<const type>(obj); +class DescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> { + public: + DescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + assert(upbdefs_google_protobuf_DescriptorProto_is(m)); + } -namespace google { -namespace protobuf { -namespace DescriptorProto { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_DescriptorProto) } -inline upb::reffed_ptr<const upb::FieldDef> enum_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_enum_type) } -inline upb::reffed_ptr<const upb::FieldDef> extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_extension) } -inline upb::reffed_ptr<const upb::FieldDef> extension_range() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_extension_range) } -inline upb::reffed_ptr<const upb::FieldDef> field() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_field) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_name) } -inline upb::reffed_ptr<const upb::FieldDef> nested_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_nested_type) } -inline upb::reffed_ptr<const upb::FieldDef> oneof_decl() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_oneof_decl) } -inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_options) } -inline upb::reffed_ptr<const upb::FieldDef> reserved_name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_reserved_name) } -inline upb::reffed_ptr<const upb::FieldDef> reserved_range() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_reserved_range) } -} /* namespace DescriptorProto */ -} /* namespace protobuf */ -} /* namespace google */ + static DescriptorProto get() { + const ::upb::MessageDef* m = upbdefs_google_protobuf_DescriptorProto_get(&m); + return DescriptorProto(m, &m); + } -namespace google { -namespace protobuf { -namespace DescriptorProto { -namespace ExtensionRange { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange) } -inline upb::reffed_ptr<const upb::FieldDef> end() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange_end) } -inline upb::reffed_ptr<const upb::FieldDef> start() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange_start) } -} /* namespace ExtensionRange */ -} /* namespace DescriptorProto */ -} /* namespace protobuf */ -} /* namespace google */ + class ExtensionRange : public ::upb::reffed_ptr<const ::upb::MessageDef> { + public: + ExtensionRange(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + assert(upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(m)); + } -namespace google { -namespace protobuf { -namespace DescriptorProto { -namespace ReservedRange { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_DescriptorProto_ReservedRange) } -inline upb::reffed_ptr<const upb::FieldDef> end() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_ReservedRange_end) } -inline upb::reffed_ptr<const upb::FieldDef> start() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_ReservedRange_start) } -} /* namespace ReservedRange */ -} /* namespace DescriptorProto */ -} /* namespace protobuf */ -} /* namespace google */ + static ExtensionRange get() { + const ::upb::MessageDef* m = upbdefs_google_protobuf_DescriptorProto_ExtensionRange_get(&m); + return ExtensionRange(m, &m); + } + }; -namespace google { -namespace protobuf { -namespace EnumDescriptorProto { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumDescriptorProto) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_name) } -inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_options) } -inline upb::reffed_ptr<const upb::FieldDef> value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_value) } -} /* namespace EnumDescriptorProto */ -} /* namespace protobuf */ -} /* namespace google */ + class ReservedRange : public ::upb::reffed_ptr<const ::upb::MessageDef> { + public: + ReservedRange(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + assert(upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(m)); + } -namespace google { -namespace protobuf { -namespace EnumOptions { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumOptions) } -inline upb::reffed_ptr<const upb::FieldDef> allow_alias() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumOptions_allow_alias) } -inline upb::reffed_ptr<const upb::FieldDef> deprecated() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumOptions_deprecated) } -inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumOptions_uninterpreted_option) } -} /* namespace EnumOptions */ -} /* namespace protobuf */ -} /* namespace google */ + static ReservedRange get() { + const ::upb::MessageDef* m = upbdefs_google_protobuf_DescriptorProto_ReservedRange_get(&m); + return ReservedRange(m, &m); + } + }; +}; -namespace google { -namespace protobuf { -namespace EnumValueDescriptorProto { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumValueDescriptorProto) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_name) } -inline upb::reffed_ptr<const upb::FieldDef> number() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_number) } -inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_options) } -} /* namespace EnumValueDescriptorProto */ -} /* namespace protobuf */ -} /* namespace google */ +class EnumDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> { + public: + EnumDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + assert(upbdefs_google_protobuf_EnumDescriptorProto_is(m)); + } -namespace google { -namespace protobuf { -namespace EnumValueOptions { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumValueOptions) } -inline upb::reffed_ptr<const upb::FieldDef> deprecated() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueOptions_deprecated) } -inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueOptions_uninterpreted_option) } -} /* namespace EnumValueOptions */ -} /* namespace protobuf */ -} /* namespace google */ + static EnumDescriptorProto get() { + const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumDescriptorProto_get(&m); + return EnumDescriptorProto(m, &m); + } +}; -namespace google { -namespace protobuf { -namespace FieldDescriptorProto { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FieldDescriptorProto) } -inline upb::reffed_ptr<const upb::FieldDef> default_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_default_value) } -inline upb::reffed_ptr<const upb::FieldDef> extendee() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_extendee) } -inline upb::reffed_ptr<const upb::FieldDef> json_name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_json_name) } -inline upb::reffed_ptr<const upb::FieldDef> label() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_label) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_name) } -inline upb::reffed_ptr<const upb::FieldDef> number() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_number) } -inline upb::reffed_ptr<const upb::FieldDef> oneof_index() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_oneof_index) } -inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_options) } -inline upb::reffed_ptr<const upb::FieldDef> type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_type) } -inline upb::reffed_ptr<const upb::FieldDef> type_name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_type_name) } -inline upb::reffed_ptr<const upb::EnumDef> Label() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldDescriptorProto_Label) } -inline upb::reffed_ptr<const upb::EnumDef> Type() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldDescriptorProto_Type) } -} /* namespace FieldDescriptorProto */ -} /* namespace protobuf */ -} /* namespace google */ +class EnumOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> { + public: + EnumOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + assert(upbdefs_google_protobuf_EnumOptions_is(m)); + } -namespace google { -namespace protobuf { -namespace FieldOptions { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FieldOptions) } -inline upb::reffed_ptr<const upb::FieldDef> ctype() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_ctype) } -inline upb::reffed_ptr<const upb::FieldDef> deprecated() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_deprecated) } -inline upb::reffed_ptr<const upb::FieldDef> jstype() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_jstype) } -inline upb::reffed_ptr<const upb::FieldDef> lazy() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_lazy) } -inline upb::reffed_ptr<const upb::FieldDef> packed() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_packed) } -inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_uninterpreted_option) } -inline upb::reffed_ptr<const upb::FieldDef> weak() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_weak) } -inline upb::reffed_ptr<const upb::EnumDef> CType() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldOptions_CType) } -inline upb::reffed_ptr<const upb::EnumDef> JSType() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldOptions_JSType) } -} /* namespace FieldOptions */ -} /* namespace protobuf */ -} /* namespace google */ + static EnumOptions get() { + const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumOptions_get(&m); + return EnumOptions(m, &m); + } +}; -namespace google { -namespace protobuf { -namespace FileDescriptorProto { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileDescriptorProto) } -inline upb::reffed_ptr<const upb::FieldDef> dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_dependency) } -inline upb::reffed_ptr<const upb::FieldDef> enum_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_enum_type) } -inline upb::reffed_ptr<const upb::FieldDef> extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_extension) } -inline upb::reffed_ptr<const upb::FieldDef> message_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_message_type) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_name) } -inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_options) } -inline upb::reffed_ptr<const upb::FieldDef> package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_package) } -inline upb::reffed_ptr<const upb::FieldDef> public_dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_public_dependency) } -inline upb::reffed_ptr<const upb::FieldDef> service() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_service) } -inline upb::reffed_ptr<const upb::FieldDef> source_code_info() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_source_code_info) } -inline upb::reffed_ptr<const upb::FieldDef> syntax() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_syntax) } -inline upb::reffed_ptr<const upb::FieldDef> weak_dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_weak_dependency) } -} /* namespace FileDescriptorProto */ -} /* namespace protobuf */ -} /* namespace google */ +class EnumValueDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> { + public: + EnumValueDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + assert(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)); + } -namespace google { -namespace protobuf { -namespace FileDescriptorSet { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileDescriptorSet) } -inline upb::reffed_ptr<const upb::FieldDef> file() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorSet_file) } -} /* namespace FileDescriptorSet */ -} /* namespace protobuf */ -} /* namespace google */ + static EnumValueDescriptorProto get() { + const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumValueDescriptorProto_get(&m); + return EnumValueDescriptorProto(m, &m); + } +}; -namespace google { -namespace protobuf { -namespace FileOptions { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileOptions) } -inline upb::reffed_ptr<const upb::FieldDef> cc_enable_arenas() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_cc_enable_arenas) } -inline upb::reffed_ptr<const upb::FieldDef> cc_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_cc_generic_services) } -inline upb::reffed_ptr<const upb::FieldDef> csharp_namespace() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_csharp_namespace) } -inline upb::reffed_ptr<const upb::FieldDef> deprecated() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_deprecated) } -inline upb::reffed_ptr<const upb::FieldDef> go_package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_go_package) } -inline upb::reffed_ptr<const upb::FieldDef> java_generate_equals_and_hash() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_generate_equals_and_hash) } -inline upb::reffed_ptr<const upb::FieldDef> java_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_generic_services) } -inline upb::reffed_ptr<const upb::FieldDef> java_multiple_files() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_multiple_files) } -inline upb::reffed_ptr<const upb::FieldDef> java_outer_classname() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_outer_classname) } -inline upb::reffed_ptr<const upb::FieldDef> java_package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_package) } -inline upb::reffed_ptr<const upb::FieldDef> java_string_check_utf8() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_string_check_utf8) } -inline upb::reffed_ptr<const upb::FieldDef> javanano_use_deprecated_package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_javanano_use_deprecated_package) } -inline upb::reffed_ptr<const upb::FieldDef> objc_class_prefix() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_objc_class_prefix) } -inline upb::reffed_ptr<const upb::FieldDef> optimize_for() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_optimize_for) } -inline upb::reffed_ptr<const upb::FieldDef> py_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_py_generic_services) } -inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_uninterpreted_option) } -inline upb::reffed_ptr<const upb::EnumDef> OptimizeMode() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FileOptions_OptimizeMode) } -} /* namespace FileOptions */ -} /* namespace protobuf */ -} /* namespace google */ +class EnumValueOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> { + public: + EnumValueOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + assert(upbdefs_google_protobuf_EnumValueOptions_is(m)); + } -namespace google { -namespace protobuf { -namespace MessageOptions { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MessageOptions) } -inline upb::reffed_ptr<const upb::FieldDef> deprecated() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_deprecated) } -inline upb::reffed_ptr<const upb::FieldDef> map_entry() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_map_entry) } -inline upb::reffed_ptr<const upb::FieldDef> message_set_wire_format() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_message_set_wire_format) } -inline upb::reffed_ptr<const upb::FieldDef> no_standard_descriptor_accessor() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_no_standard_descriptor_accessor) } -inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_uninterpreted_option) } -} /* namespace MessageOptions */ -} /* namespace protobuf */ -} /* namespace google */ + static EnumValueOptions get() { + const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumValueOptions_get(&m); + return EnumValueOptions(m, &m); + } +}; -namespace google { -namespace protobuf { -namespace MethodDescriptorProto { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MethodDescriptorProto) } -inline upb::reffed_ptr<const upb::FieldDef> client_streaming() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_client_streaming) } -inline upb::reffed_ptr<const upb::FieldDef> input_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_input_type) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_name) } -inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_options) } -inline upb::reffed_ptr<const upb::FieldDef> output_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_output_type) } -inline upb::reffed_ptr<const upb::FieldDef> server_streaming() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_server_streaming) } -} /* namespace MethodDescriptorProto */ -} /* namespace protobuf */ -} /* namespace google */ +class FieldDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> { + public: + FieldDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + assert(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); + } -namespace google { -namespace protobuf { -namespace MethodOptions { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MethodOptions) } -inline upb::reffed_ptr<const upb::FieldDef> deprecated() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodOptions_deprecated) } -inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodOptions_uninterpreted_option) } -} /* namespace MethodOptions */ -} /* namespace protobuf */ -} /* namespace google */ + static FieldDescriptorProto get() { + const ::upb::MessageDef* m = upbdefs_google_protobuf_FieldDescriptorProto_get(&m); + return FieldDescriptorProto(m, &m); + } -namespace google { -namespace protobuf { -namespace OneofDescriptorProto { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_OneofDescriptorProto) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_OneofDescriptorProto_name) } -} /* namespace OneofDescriptorProto */ -} /* namespace protobuf */ -} /* namespace google */ + class Label : public ::upb::reffed_ptr<const ::upb::EnumDef> { + public: + Label(const ::upb::EnumDef* e, const void *ref_donor = NULL) + : reffed_ptr(e, ref_donor) { + 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); + } + }; -namespace google { -namespace protobuf { -namespace ServiceDescriptorProto { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_ServiceDescriptorProto) } -inline upb::reffed_ptr<const upb::FieldDef> method() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_method) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_name) } -inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_options) } -} /* namespace ServiceDescriptorProto */ -} /* namespace protobuf */ -} /* namespace google */ + class Type : public ::upb::reffed_ptr<const ::upb::EnumDef> { + public: + Type(const ::upb::EnumDef* e, const void *ref_donor = NULL) + : reffed_ptr(e, ref_donor) { + 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); + } + }; +}; -namespace google { -namespace protobuf { -namespace ServiceOptions { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_ServiceOptions) } -inline upb::reffed_ptr<const upb::FieldDef> deprecated() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceOptions_deprecated) } -inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceOptions_uninterpreted_option) } -} /* namespace ServiceOptions */ -} /* namespace protobuf */ -} /* namespace google */ +class FieldOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> { + public: + FieldOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + assert(upbdefs_google_protobuf_FieldOptions_is(m)); + } -namespace google { -namespace protobuf { -namespace SourceCodeInfo { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_SourceCodeInfo) } -inline upb::reffed_ptr<const upb::FieldDef> location() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_location) } -} /* namespace SourceCodeInfo */ -} /* namespace protobuf */ -} /* namespace google */ + static FieldOptions get() { + const ::upb::MessageDef* m = upbdefs_google_protobuf_FieldOptions_get(&m); + return FieldOptions(m, &m); + } -namespace google { -namespace protobuf { -namespace SourceCodeInfo { -namespace Location { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_SourceCodeInfo_Location) } -inline upb::reffed_ptr<const upb::FieldDef> leading_comments() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_leading_comments) } -inline upb::reffed_ptr<const upb::FieldDef> leading_detached_comments() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_leading_detached_comments) } -inline upb::reffed_ptr<const upb::FieldDef> path() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_path) } -inline upb::reffed_ptr<const upb::FieldDef> span() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_span) } -inline upb::reffed_ptr<const upb::FieldDef> trailing_comments() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_trailing_comments) } -} /* namespace Location */ -} /* namespace SourceCodeInfo */ -} /* namespace protobuf */ -} /* namespace google */ + class CType : public ::upb::reffed_ptr<const ::upb::EnumDef> { + public: + CType(const ::upb::EnumDef* e, const void *ref_donor = NULL) + : reffed_ptr(e, ref_donor) { + 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); + } + }; -namespace google { -namespace protobuf { -namespace UninterpretedOption { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_UninterpretedOption) } -inline upb::reffed_ptr<const upb::FieldDef> aggregate_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_aggregate_value) } -inline upb::reffed_ptr<const upb::FieldDef> double_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_double_value) } -inline upb::reffed_ptr<const upb::FieldDef> identifier_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_identifier_value) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_name) } -inline upb::reffed_ptr<const upb::FieldDef> negative_int_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_negative_int_value) } -inline upb::reffed_ptr<const upb::FieldDef> positive_int_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_positive_int_value) } -inline upb::reffed_ptr<const upb::FieldDef> string_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_string_value) } -} /* namespace UninterpretedOption */ -} /* namespace protobuf */ -} /* namespace google */ + class JSType : public ::upb::reffed_ptr<const ::upb::EnumDef> { + public: + JSType(const ::upb::EnumDef* e, const void *ref_donor = NULL) + : reffed_ptr(e, ref_donor) { + 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<const ::upb::MessageDef> { + public: + FileDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + 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<const ::upb::MessageDef> { + public: + FileDescriptorSet(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + 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<const ::upb::MessageDef> { + public: + FileOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + 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<const ::upb::EnumDef> { + public: + OptimizeMode(const ::upb::EnumDef* e, const void *ref_donor = NULL) + : reffed_ptr(e, ref_donor) { + 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<const ::upb::MessageDef> { + public: + MessageOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + 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<const ::upb::MessageDef> { + public: + MethodDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + 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<const ::upb::MessageDef> { + public: + MethodOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + 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<const ::upb::MessageDef> { + public: + OneofDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + 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<const ::upb::MessageDef> { + public: + ServiceDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + 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<const ::upb::MessageDef> { + public: + ServiceOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + 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<const ::upb::MessageDef> { + public: + SourceCodeInfo(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + 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<const ::upb::MessageDef> { + public: + Location(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + 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<const ::upb::MessageDef> { + public: + UninterpretedOption(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + 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<const ::upb::MessageDef> { + public: + NamePart(const ::upb::MessageDef* m, const void *ref_donor = NULL) + : reffed_ptr(m, ref_donor) { + 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 google { -namespace protobuf { -namespace UninterpretedOption { -namespace NamePart { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_UninterpretedOption_NamePart) } -inline upb::reffed_ptr<const upb::FieldDef> is_extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_NamePart_is_extension) } -inline upb::reffed_ptr<const upb::FieldDef> name_part() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_NamePart_name_part) } -} /* namespace NamePart */ -} /* namespace UninterpretedOption */ } /* namespace protobuf */ } /* namespace google */ - } /* namespace upbdefs */ +#endif /* __cplusplus */ -#undef RETURN_REFFED -#endif /* __cplusplus */ - -#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_ */ +#endif /* UPB_DESCRIPTOR_DESCRIPTOR_PROTO_UPB_H_ */ /* ** Internal-only definitions for the decoder. */ @@ -7242,7 +7327,6 @@ inline upb::reffed_ptr<const upb::FieldDef> name_part() { RETURN_REFFED(upb::Fie #ifndef UPB_DECODER_INT_H_ #define UPB_DECODER_INT_H_ -#include <stdlib.h> /* ** upb::pb::Decoder ** @@ -7342,7 +7426,7 @@ class upb::pb::DecoderMethod { * 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 4408 +#define UPB_PB_DECODER_SIZE 4416 #ifdef __cplusplus @@ -8155,49 +8239,44 @@ inline reffed_ptr<const Handlers> Encoder::NewHandlers( #include <stdbool.h> #ifdef __cplusplus +#include <vector> + extern "C" { #endif -/* Loads all defs from the given protobuf binary descriptor, setting default - * accessors and a default layout on all messages. The caller owns the - * returned array of defs, which will be of length *n. On error NULL is - * returned and status is set (if non-NULL). */ -upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n, - void *owner, upb_status *status); - -/* Like the previous but also adds the loaded defs to the given symtab. */ -bool upb_load_descriptor_into_symtab(upb_symtab *symtab, const char *str, - size_t len, upb_status *status); - -/* Like the previous but also reads the descriptor from the given filename. */ -bool upb_load_descriptor_file_into_symtab(upb_symtab *symtab, const char *fname, - upb_status *status); - -/* Reads the given filename into a character string, returning NULL if there - * was an error. */ -char *upb_readfile(const char *filename, size_t *len); +/* 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 { -/* All routines that load descriptors expect the descriptor to be a - * FileDescriptorSet. */ -inline bool LoadDescriptorFileIntoSymtab(SymbolTable* s, const char *fname, - Status* status) { - return upb_load_descriptor_file_into_symtab(s, fname, status); -} +inline bool LoadDescriptor(const char* buf, size_t n, Status* status, + std::vector<reffed_ptr<FileDef> >* files) { + FileDef** parsed_files = upb_loaddescriptor(buf, n, &parsed_files, status); -inline bool LoadDescriptorIntoSymtab(SymbolTable* s, const char* str, - size_t len, Status* status) { - return upb_load_descriptor_into_symtab(s, str, len, status); + if (parsed_files) { + FileDef** p = parsed_files; + while (*p) { + files->push_back(reffed_ptr<FileDef>(*p, &parsed_files)); + ++p; + } + free(parsed_files); + return true; + } else { + return false; + } } /* Templated so it can accept both string and std::string. */ template <typename T> -bool LoadDescriptorIntoSymtab(SymbolTable* s, const T& desc, Status* status) { - return upb_load_descriptor_into_symtab(s, desc.c_str(), desc.size(), status); +bool LoadDescriptor(const T& desc, Status* status, + std::vector<reffed_ptr<FileDef> >* files) { + return LoadDescriptor(desc.c_str(), desc.size(), status, files); } } /* namespace upb */ @@ -8314,7 +8393,7 @@ UPB_DECLARE_DERIVED_TYPE(upb::json::ParserMethod, upb::RefCounted, * 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 4104 +#define UPB_JSON_PARSER_SIZE 4112 #ifdef __cplusplus @@ -8427,7 +8506,7 @@ UPB_DECLARE_TYPE(upb::json::Printer, upb_json_printer) /* upb::json::Printer *********************************************************/ -#define UPB_JSON_PRINTER_SIZE 168 +#define UPB_JSON_PRINTER_SIZE 176 #ifdef __cplusplus @@ -8440,8 +8519,12 @@ class upb::json::Printer { /* The input to the printer. */ Sink* input(); - /* Returns handlers for printing according to the specified schema. */ - static reffed_ptr<const Handlers> NewHandlers(const upb::MessageDef* md); + /* 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<const Handlers> NewHandlers(const upb::MessageDef* md, + bool preserve_proto_fieldnames); static const size_t kSize = UPB_JSON_PRINTER_SIZE; @@ -8458,6 +8541,7 @@ 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 @@ -8472,8 +8556,9 @@ inline Printer* Printer::Create(Environment* env, const upb::Handlers* handlers, } inline Sink* Printer::input() { return upb_json_printer_input(this); } inline reffed_ptr<const Handlers> Printer::NewHandlers( - const upb::MessageDef *md) { - const Handlers* h = upb_json_printer_newhandlers(md, &h); + const upb::MessageDef *md, bool preserve_proto_fieldnames) { + const Handlers* h = upb_json_printer_newhandlers( + md, preserve_proto_fieldnames, &h); return reffed_ptr<const Handlers>(h, &h); } } /* namespace json */ diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec index 7b64ee77..1fa626fe 100644 --- a/ruby/google-protobuf.gemspec +++ b/ruby/google-protobuf.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = "google-protobuf" - s.version = "3.0.0.alpha.5.0" + s.version = "3.0.0.alpha.5.0.5" s.licenses = ["BSD"] s.summary = "Protocol Buffers" s.description = "Protocol Buffers are Google's data interchange format." diff --git a/ruby/lib/google/protobuf/repeated_field.rb b/ruby/lib/google/protobuf/repeated_field.rb index 16c843c0..0ad2060d 100644 --- a/ruby/lib/google/protobuf/repeated_field.rb +++ b/ruby/lib/google/protobuf/repeated_field.rb @@ -69,8 +69,8 @@ module Google # relationship explicit instead of implicit def_delegators :to_ary, :&, :*, :-, :'<=>', - :assoc, :bsearch, :combination, :compact, :count, :cycle, - :drop, :drop_while, :eql?, :fetch, :find_index, :flatten, + :assoc, :bsearch, :bsearch_index, :combination, :compact, :count, + :cycle, :dig, :drop, :drop_while, :eql?, :fetch, :find_index, :flatten, :include?, :index, :inspect, :join, :pack, :permutation, :product, :pretty_print, :pretty_print_cycle, :rassoc, :repeated_combination, :repeated_permutation, :reverse, diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb index 86c74c2a..77c186ef 100644 --- a/ruby/tests/basic.rb +++ b/ruby/tests/basic.rb @@ -1161,7 +1161,12 @@ module BasicTest 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 MapMessage.encode_json(m) == expected + + json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true) + assert json == expected_preserve + m2 = MapMessage.decode_json(MapMessage.encode_json(m)) assert m == m2 end diff --git a/src/Makefile.am b/src/Makefile.am index 2ba0ef9b..80065506 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -507,6 +507,8 @@ protoc_inputs = \ google/protobuf/unittest_preserve_unknown_enum.proto \ google/protobuf/unittest.proto \ google/protobuf/unittest_proto3_arena.proto \ + google/protobuf/unittest_proto3_arena_lite.proto \ + google/protobuf/unittest_proto3_lite.proto \ google/protobuf/unittest_well_known_types.proto \ google/protobuf/util/internal/testdata/anys.proto \ google/protobuf/util/internal/testdata/books.proto \ @@ -609,6 +611,10 @@ protoc_outputs = \ google/protobuf/unittest_preserve_unknown_enum.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_well_known_types.pb.cc \ google/protobuf/unittest_well_known_types.pb.h \ google/protobuf/util/internal/testdata/anys.pb.cc \ @@ -710,6 +716,8 @@ protobuf_test_SOURCES = \ 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_lite_unittest.cc \ google/protobuf/reflection_ops_unittest.cc \ google/protobuf/repeated_field_reflection_unittest.cc \ google/protobuf/repeated_field_unittest.cc \ diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc index e8878ba4..fbde4a6d 100644 --- a/src/google/protobuf/any.pb.cc +++ b/src/google/protobuf/any.pb.cc @@ -196,13 +196,14 @@ Any* Any::New(::google::protobuf::Arena* arena) const { } void Any::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Any) type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } bool Any::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.Any) for (;;) { @@ -308,6 +309,7 @@ void Any::SerializeWithCachedSizes( } int Any::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any) int total_size = 0; // optional string type_url = 1; @@ -331,18 +333,22 @@ int Any::ByteSize() const { } void Any::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Any) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const Any* source = ::google::protobuf::internal::DynamicCastToGenerated<const Any>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Any) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Any) MergeFrom(*source); } } void Any::MergeFrom(const Any& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Any) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from.type_url().size() > 0) { @@ -355,12 +361,14 @@ void Any::MergeFrom(const Any& from) { } void Any::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Any) if (&from == this) return; Clear(); MergeFrom(from); } void Any::CopyFrom(const Any& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Any) if (&from == this) return; Clear(); MergeFrom(from); @@ -423,6 +431,7 @@ void Any::clear_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()); } @@ -466,6 +475,7 @@ void Any::clear_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()); } diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h index 82c70ad9..100a67f6 100644 --- a/src/google/protobuf/any.pb.h +++ b/src/google/protobuf/any.pb.h @@ -184,6 +184,7 @@ inline ::std::string* Any::mutable_type_url() { return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -227,6 +228,7 @@ inline ::std::string* Any::mutable_value() { return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline ::std::string* Any::release_value() { + // @@protoc_insertion_point(field_release:google.protobuf.Any.value) return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto index 47d288c3..45db6ede 100644 --- a/src/google/protobuf/any.proto +++ b/src/google/protobuf/any.proto @@ -110,6 +110,8 @@ message Any { // * If no schema 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 diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc index e589a89d..cbeba302 100644 --- a/src/google/protobuf/api.pb.cc +++ b/src/google/protobuf/api.pb.cc @@ -265,6 +265,7 @@ Api* Api::New(::google::protobuf::Arena* arena) const { } void Api::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Api) name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_; @@ -277,7 +278,7 @@ void Api::Clear() { bool Api::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.Api) for (;;) { @@ -538,6 +539,7 @@ void Api::SerializeWithCachedSizes( } int Api::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Api) int total_size = 0; // optional string name = 1; @@ -598,18 +600,22 @@ int Api::ByteSize() const { } void Api::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Api) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const Api* source = ::google::protobuf::internal::DynamicCastToGenerated<const Api>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Api) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Api) MergeFrom(*source); } } void Api::MergeFrom(const Api& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Api) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); methods_.MergeFrom(from.methods_); options_.MergeFrom(from.options_); @@ -631,12 +637,14 @@ void Api::MergeFrom(const Api& from) { } void Api::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Api) if (&from == this) return; Clear(); MergeFrom(from); } void Api::CopyFrom(const Api& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Api) if (&from == this) return; Clear(); MergeFrom(from); @@ -704,6 +712,7 @@ void Api::clear_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()); } @@ -807,6 +816,7 @@ void Api::clear_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()); } @@ -841,6 +851,7 @@ const ::google::protobuf::SourceContext& Api::source_context() const { 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; @@ -984,8 +995,17 @@ Method* Method::New(::google::protobuf::Arena* arena) const { } void Method::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Method) +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(Method, f) \ + _Pragma("clang diagnostic pop") +#else #define ZR_HELPER_(f) reinterpret_cast<char*>(\ &reinterpret_cast<Method*>(16)->f) +#endif #define ZR_(first, last) do {\ ::memset(&first, 0,\ @@ -1005,7 +1025,7 @@ void Method::Clear() { bool Method::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.Method) for (;;) { @@ -1269,6 +1289,7 @@ void Method::SerializeWithCachedSizes( } int Method::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Method) int total_size = 0; // optional string name = 1; @@ -1323,18 +1344,22 @@ int Method::ByteSize() const { } void Method::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Method) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const Method* source = ::google::protobuf::internal::DynamicCastToGenerated<const Method>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Method) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Method) MergeFrom(*source); } } void Method::MergeFrom(const Method& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Method) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); options_.MergeFrom(from.options_); if (from.name().size() > 0) { @@ -1361,12 +1386,14 @@ void Method::MergeFrom(const Method& from) { } void Method::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Method) if (&from == this) return; Clear(); MergeFrom(from); } void Method::CopyFrom(const Method& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Method) if (&from == this) return; Clear(); MergeFrom(from); @@ -1434,6 +1461,7 @@ void Method::clear_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()); } @@ -1477,6 +1505,7 @@ void Method::clear_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()); } @@ -1534,6 +1563,7 @@ void Method::clear_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()); } @@ -1678,13 +1708,14 @@ Mixin* Mixin::New(::google::protobuf::Arena* arena) const { } void Mixin::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Mixin) name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); root_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } bool Mixin::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.Mixin) for (;;) { @@ -1802,6 +1833,7 @@ void Mixin::SerializeWithCachedSizes( } int Mixin::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Mixin) int total_size = 0; // optional string name = 1; @@ -1825,18 +1857,22 @@ int Mixin::ByteSize() const { } void Mixin::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Mixin) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const Mixin* source = ::google::protobuf::internal::DynamicCastToGenerated<const Mixin>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Mixin) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Mixin) MergeFrom(*source); } } void Mixin::MergeFrom(const Mixin& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Mixin) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from.name().size() > 0) { @@ -1849,12 +1885,14 @@ void Mixin::MergeFrom(const Mixin& from) { } void Mixin::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Mixin) if (&from == this) return; Clear(); MergeFrom(from); } void Mixin::CopyFrom(const Mixin& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Mixin) if (&from == this) return; Clear(); MergeFrom(from); @@ -1917,6 +1955,7 @@ void Mixin::clear_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()); } @@ -1960,6 +1999,7 @@ void Mixin::clear_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()); } diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h index e1dca4e4..bb35e471 100644 --- a/src/google/protobuf/api.pb.h +++ b/src/google/protobuf/api.pb.h @@ -468,6 +468,7 @@ inline ::std::string* Api::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline ::std::string* Api::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Api.name) return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -571,6 +572,7 @@ inline ::std::string* Api::mutable_version() { return version_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline ::std::string* Api::release_version() { + // @@protoc_insertion_point(field_release:google.protobuf.Api.version) return version_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -605,6 +607,7 @@ inline ::google::protobuf::SourceContext* Api::mutable_source_context() { return source_context_; } inline ::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; @@ -699,6 +702,7 @@ inline ::std::string* Method::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline ::std::string* Method::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Method.name) return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -742,6 +746,7 @@ inline ::std::string* Method::mutable_request_type_url() { return request_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -799,6 +804,7 @@ inline ::std::string* Method::mutable_response_type_url() { return response_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -904,6 +910,7 @@ inline ::std::string* Mixin::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline ::std::string* Mixin::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Mixin.name) return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -947,6 +954,7 @@ inline ::std::string* Mixin::mutable_root() { return root_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline ::std::string* Mixin::release_root() { + // @@protoc_insertion_point(field_release:google.protobuf.Mixin.root) return root_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc index e856f5b1..613e5897 100755 --- a/src/google/protobuf/arena.cc +++ b/src/google/protobuf/arena.cc @@ -30,6 +30,7 @@ #include <google/protobuf/arena.h> + #ifdef ADDRESS_SANITIZER #include <sanitizer/asan_interface.h> #endif @@ -248,6 +249,19 @@ uint64 Arena::SpaceUsed() const { return space_used; } +pair<uint64, uint64> Arena::SpaceAllocatedAndUsed() const { + uint64 allocated = 0; + uint64 used = 0; + + Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_)); + while (b != NULL) { + allocated += b->size; + used += (b->pos - kHeaderSize); + b = b->next; + } + return std::make_pair(allocated, used); +} + uint64 Arena::FreeBlocks() { uint64 space_allocated = 0; Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_)); diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index 9ab0a0f9..b3d66d91 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -211,7 +211,12 @@ struct ArenaOptions { // // This protocol is implemented by all arena-enabled proto2 message classes as // well as RepeatedPtrField. + +#if __cplusplus >= 201103L +class Arena final { +#else class LIBPROTOBUF_EXPORT Arena { +#endif public: // Arena constructor taking custom options. See ArenaOptions below for // descriptions of the options available. @@ -231,7 +236,6 @@ class LIBPROTOBUF_EXPORT Arena { // if it was passed in. ~Arena(); - // 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 // defined in a .proto file with cc_enable_arenas set to true, otherwise a @@ -448,6 +452,10 @@ class LIBPROTOBUF_EXPORT Arena { // As above, but does not include any free space in underlying blocks. GOOGLE_ATTRIBUTE_NOINLINE uint64 SpaceUsed() const; + // Combines SpaceAllocated and SpaceUsed. Returns a pair of + // <space_allocated, space_used>. + GOOGLE_ATTRIBUTE_NOINLINE pair<uint64, uint64> SpaceAllocatedAndUsed() const; + // 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 diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc index 6b67f446..ab25ffe1 100644 --- a/src/google/protobuf/arena_unittest.cc +++ b/src/google/protobuf/arena_unittest.cc @@ -342,6 +342,64 @@ TEST(ArenaTest, Swap) { EXPECT_EQ(42, arena2_message->unknown_fields().field(0).varint()); } +TEST(ArenaTest, ReflectionSwapFields) { + Arena arena1; + Arena arena2; + TestAllTypes* arena1_message; + TestAllTypes* arena2_message; + + // Case 1: messages on different arenas, only one message is set. + arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1); + arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2); + TestUtil::SetAllFields(arena1_message); + const Reflection* reflection = arena1_message->GetReflection(); + std::vector<const FieldDescriptor*> fields; + reflection->ListFields(*arena1_message, &fields); + reflection->SwapFields(arena1_message, arena2_message, fields); + EXPECT_EQ(&arena1, arena1_message->GetArena()); + EXPECT_EQ(&arena2, arena2_message->GetArena()); + string output; + arena1_message->SerializeToString(&output); + EXPECT_EQ(0, output.size()); + TestUtil::ExpectAllFieldsSet(*arena2_message); + reflection->SwapFields(arena1_message, arena2_message, fields); + arena2_message->SerializeToString(&output); + EXPECT_EQ(0, output.size()); + TestUtil::ExpectAllFieldsSet(*arena1_message); + + // Case 2: messages on different arenas, both messages are set. + arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1); + arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2); + TestUtil::SetAllFields(arena1_message); + TestUtil::SetAllFields(arena2_message); + reflection->SwapFields(arena1_message, arena2_message, fields); + EXPECT_EQ(&arena1, arena1_message->GetArena()); + EXPECT_EQ(&arena2, arena2_message->GetArena()); + TestUtil::ExpectAllFieldsSet(*arena1_message); + TestUtil::ExpectAllFieldsSet(*arena2_message); + + // Case 3: messages on different arenas with different lifetimes. + arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1); + { + Arena arena3; + TestAllTypes* arena3_message = Arena::CreateMessage<TestAllTypes>(&arena3); + TestUtil::SetAllFields(arena3_message); + reflection->SwapFields(arena1_message, arena3_message, fields); + } + TestUtil::ExpectAllFieldsSet(*arena1_message); + + // Case 4: one message on arena, the other on heap. + arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1); + TestAllTypes message; + TestUtil::SetAllFields(arena1_message); + reflection->SwapFields(arena1_message, &message, fields); + EXPECT_EQ(&arena1, arena1_message->GetArena()); + EXPECT_EQ(NULL, message.GetArena()); + arena1_message->SerializeToString(&output); + EXPECT_EQ(0, output.size()); + TestUtil::ExpectAllFieldsSet(message); +} + TEST(ArenaTest, SetAllocatedMessage) { Arena arena; TestAllTypes *arena_message = Arena::CreateMessage<TestAllTypes>(&arena); diff --git a/src/google/protobuf/arenastring_unittest.cc b/src/google/protobuf/arenastring_unittest.cc index 3fb582be..ea405d7d 100644 --- a/src/google/protobuf/arenastring_unittest.cc +++ b/src/google/protobuf/arenastring_unittest.cc @@ -28,9 +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. -// arenastring_unittest.cc is not open-sourced. Do not include in open-source -// distribution. - // Based on mvels@'s frankenstring. #include <google/protobuf/arenastring.h> diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 87843f62..fcad6b61 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -46,6 +46,7 @@ #include <unistd.h> #endif #include <errno.h> +#include <fstream> #include <iostream> #include <ctype.h> @@ -948,17 +949,23 @@ bool CommandLineInterface::MakeInputsBeProtoPathRelative( return true; } + CommandLineInterface::ParseArgumentStatus CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { executable_name_ = argv[0]; + vector<string> arguments; + for (int i = 1; i < argc; ++i) { + arguments.push_back(argv[i]); + } + // Iterate through all arguments and parse them. - for (int i = 1; i < argc; i++) { + for (int i = 0; i < arguments.size(); ++i) { string name, value; - if (ParseArgument(argv[i], &name, &value)) { + if (ParseArgument(arguments[i].c_str(), &name, &value)) { // Returned true => Use the next argument as the flag value. - if (i + 1 == argc || argv[i+1][0] == '-') { + if (i + 1 == arguments.size() || arguments[i + 1][0] == '-') { std::cerr << "Missing value for flag: " << name << std::endl; if (name == "--decode") { std::cerr << "To decode an unknown message, use --decode_raw." @@ -967,7 +974,7 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { return PARSE_ARGUMENT_FAIL; } else { ++i; - value = argv[i]; + value = arguments[i]; } } diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index f196ffc5..d1377666 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -212,6 +212,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { // Parse all command-line arguments. ParseArgumentStatus ParseArguments(int argc, const char* const argv[]); + // 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, // false otherwise. diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index e3dd2295..ae2900b1 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -60,6 +60,7 @@ #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/substitute.h> +#include <google/protobuf/testing/file.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> @@ -376,7 +377,9 @@ void CommandLineInterfaceTest::CreateTempFile( // Write file. string full_name = temp_directory_ + "/" + name; - GOOGLE_CHECK_OK(File::SetContents(full_name, contents, true)); + GOOGLE_CHECK_OK(File::SetContents( + full_name, StringReplace(contents, "$tmpdir", temp_directory_, true), + true)); } void CommandLineInterfaceTest::CreateTempDir(const string& name) { @@ -1090,6 +1093,7 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForAbsolutePath) { } #endif // !_WIN32 + // ------------------------------------------------------------------- TEST_F(CommandLineInterfaceTest, ParseErrors) { diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc index 47729e1c..77451ab1 100644 --- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc @@ -54,6 +54,7 @@ #include <google/protobuf/stubs/substitute.h> #include <google/protobuf/testing/file.h> +#include <google/protobuf/testing/file.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc index 415ae60f..c81c5982 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc @@ -98,9 +98,11 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { vars["number"] = Int32ToString(descriptor_->value(i)->number()); vars["prefix"] = (descriptor_->containing_type() == NULL) ? "" : classname_ + "_"; + vars["deprecation"] = descriptor_->value(i)->options().deprecated() ? + " PROTOBUF_DEPRECATED" : ""; if (i > 0) printer->Print(",\n"); - printer->Print(vars, "$prefix$$name$ = $number$"); + printer->Print(vars, "$prefix$$name$$deprecation$ = $number$"); if (descriptor_->value(i)->number() < min_value->number()) { min_value = descriptor_->value(i); @@ -142,15 +144,16 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { "$prefix$$short_name$_MAX + 1;\n\n"); } - if (HasDescriptorMethods(descriptor_->file())) { + 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" - "}\n"); + printer->Print( + vars, + "inline const ::std::string& $classname$_Name($classname$ value) {\n" + " return ::google::protobuf::internal::NameOfEnum(\n" + " $classname$_descriptor(), value);\n" + "}\n"); printer->Print(vars, "inline bool $classname$_Parse(\n" " const ::std::string& name, $classname$* value) {\n" @@ -166,7 +169,7 @@ GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type " "{};\n", "classname", ClassName(descriptor_, true)); - if (HasDescriptorMethods(descriptor_->file())) { + if (HasDescriptorMethods(descriptor_->file(), options_)) { printer->Print( "template <>\n" "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n" @@ -185,8 +188,11 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) { for (int j = 0; j < descriptor_->value_count(); j++) { vars["tag"] = EnumValueName(descriptor_->value(j)); + vars["deprecated_attr"] = descriptor_->value(j)->options().deprecated() ? + "PROTOBUF_DEPRECATED_ATTR " : ""; printer->Print(vars, - "static $constexpr$const $nested_name$ $tag$ = $classname$_$tag$;\n"); + "$deprecated_attr$static $constexpr$const $nested_name$ $tag$ =\n" + " $classname$_$tag$;\n"); } printer->Print(vars, @@ -203,16 +209,18 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) { " $classname$_$nested_name$_ARRAYSIZE;\n"); } - if (HasDescriptorMethods(descriptor_->file())) { + if (HasDescriptorMethods(descriptor_->file(), options_)) { printer->Print(vars, "static inline const ::google::protobuf::EnumDescriptor*\n" "$nested_name$_descriptor() {\n" " return $classname$_descriptor();\n" "}\n"); printer->Print(vars, - "static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n" - " return $classname$_Name(value);\n" - "}\n"); + "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" @@ -242,7 +250,7 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) { vars["classname"] = classname_; vars["constexpr"] = options_.proto_h ? "constexpr " : ""; - if (HasDescriptorMethods(descriptor_->file())) { + if (HasDescriptorMethods(descriptor_->file(), options_)) { printer->Print(vars, "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n" " protobuf_AssignDescriptorsOnce();\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h index 61e40346..90edf001 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum.h @@ -35,12 +35,12 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__ +#include <map> #include <set> #include <string> #include <google/protobuf/compiler/cpp/cpp_options.h> #include <google/protobuf/descriptor.h> - namespace google { namespace protobuf { namespace io { @@ -55,8 +55,7 @@ namespace cpp { class EnumGenerator { public: // See generator.cc for the meaning of dllexport_decl. - explicit EnumGenerator(const EnumDescriptor* descriptor, - const Options& options); + EnumGenerator(const EnumDescriptor* descriptor, const Options& options); ~EnumGenerator(); // Header stuff. @@ -96,10 +95,10 @@ class EnumGenerator { private: const EnumDescriptor* descriptor_; - string classname_; - Options options_; + const string classname_; + const Options& options_; // whether to generate the *_ARRAYSIZE constant. - bool generate_array_size_; + const bool generate_array_size_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); }; diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc index 06cb18d1..10252b39 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc @@ -59,10 +59,9 @@ void SetEnumVariables(const FieldDescriptor* descriptor, // =================================================================== -EnumFieldGenerator:: -EnumFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : descriptor_(descriptor) { +EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : FieldGenerator(options), descriptor_(descriptor) { SetEnumVariables(descriptor, &variables_, options); } @@ -76,8 +75,8 @@ GeneratePrivateMembers(io::Printer* printer) const { void EnumFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "$type$ $name$() const$deprecation$;\n" - "void set_$name$($type$ value)$deprecation$;\n"); + "$deprecated_attr$$type$ $name$() const;\n" + "$deprecated_attr$void set_$name$($type$ value);\n"); } void EnumFieldGenerator:: @@ -136,7 +135,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { printer->Print(variables_, "if ($type$_IsValid(value)) {\n" " set_$name$(static_cast< $type$ >(value));\n"); - if (UseUnknownFieldSet(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print(variables_, "} else {\n" " mutable_unknown_fields()->AddVarint($number$, value);\n"); @@ -230,10 +229,9 @@ GenerateConstructorCode(io::Printer* printer) const { // =================================================================== -RepeatedEnumFieldGenerator:: -RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : descriptor_(descriptor) { +RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator( + const FieldDescriptor* descriptor, const Options& options) + : FieldGenerator(options), descriptor_(descriptor) { SetEnumVariables(descriptor, &variables_, options); } @@ -243,8 +241,8 @@ void RepeatedEnumFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { printer->Print(variables_, "::google::protobuf::RepeatedField<int> $name$_;\n"); - if (descriptor_->is_packed() - && HasGeneratedMethods(descriptor_->file())) { + if (descriptor_->is_packed() && + HasGeneratedMethods(descriptor_->file(), options_)) { printer->Print(variables_, "mutable int _$name$_cached_byte_size_;\n"); } @@ -253,12 +251,12 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedEnumFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "$type$ $name$(int index) const$deprecation$;\n" - "void set_$name$(int index, $type$ value)$deprecation$;\n" - "void add_$name$($type$ value)$deprecation$;\n"); + "$deprecated_attr$$type$ $name$(int index) const;\n" + "$deprecated_attr$void set_$name$(int index, $type$ value);\n" + "$deprecated_attr$void add_$name$($type$ value);\n"); printer->Print(variables_, - "const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n" - "::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n"); + "$deprecated_attr$const ::google::protobuf::RepeatedField<int>& $name$() const;\n" + "$deprecated_attr$::google::protobuf::RepeatedField<int>* mutable_$name$();\n"); } void RepeatedEnumFieldGenerator:: @@ -337,7 +335,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { printer->Print(variables_, "if ($type$_IsValid(value)) {\n" " add_$name$(static_cast< $type$ >(value));\n"); - if (UseUnknownFieldSet(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print(variables_, "} else {\n" " mutable_unknown_fields()->AddVarint($number$, value);\n"); @@ -364,7 +362,7 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { " NULL,\n" " NULL,\n" " this->mutable_$name$())));\n"); - } else if (UseUnknownFieldSet(descriptor_->file())) { + } else if (UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print(variables_, "DO_((::google::protobuf::internal::WireFormat::ReadPackedEnumPreserveUnknowns(\n" " input,\n" @@ -401,7 +399,7 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { " if ($type$_IsValid(value)) {\n" " add_$name$(static_cast< $type$ >(value));\n" " } else {\n"); - if (UseUnknownFieldSet(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print(variables_, " mutable_unknown_fields()->AddVarint($number$, value);\n"); } else { diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h index 5b1d01ea..fe21c575 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h @@ -46,8 +46,7 @@ namespace cpp { class EnumFieldGenerator : public FieldGenerator { public: - explicit EnumFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options); ~EnumFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -74,8 +73,8 @@ class EnumFieldGenerator : public FieldGenerator { class EnumOneofFieldGenerator : public EnumFieldGenerator { public: - explicit EnumOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + EnumOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~EnumOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -91,8 +90,8 @@ class EnumOneofFieldGenerator : public EnumFieldGenerator { class RepeatedEnumFieldGenerator : public FieldGenerator { public: - explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~RepeatedEnumFieldGenerator(); // implements FieldGenerator --------------------------------------- diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc index 8d47d4e0..b3ba3a2e 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_field.cc @@ -77,6 +77,8 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, WireFormat::TagSize(descriptor->number(), descriptor->type())); (*variables)["deprecation"] = descriptor->options().deprecated() ? " PROTOBUF_DEPRECATED" : ""; + (*variables)["deprecated_attr"] = descriptor->options().deprecated() + ? "PROTOBUF_DEPRECATED_ATTR " : ""; (*variables)["cppget"] = "Get"; @@ -121,6 +123,7 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, const Options& options) : descriptor_(descriptor), + options_(options), field_generators_( new google::protobuf::scoped_ptr<FieldGenerator>[descriptor->field_count()]) { // Construct all the FieldGenerators. diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h index 1d7f8233..3b012527 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_field.h @@ -69,7 +69,7 @@ void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor, class FieldGenerator { public: - FieldGenerator() {} + explicit FieldGenerator(const Options& options) : options_(options) {} virtual ~FieldGenerator(); // Generate lines of code declaring members fields of the message class @@ -194,6 +194,9 @@ class FieldGenerator { // are placed in the message's ByteSize() method. virtual void GenerateByteSize(io::Printer* printer) const = 0; + protected: + const Options& options_; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator); }; @@ -201,13 +204,14 @@ class FieldGenerator { // Convenience class which constructs FieldGenerators for a Descriptor. class FieldGeneratorMap { public: - explicit FieldGeneratorMap(const Descriptor* descriptor, const Options& options); + FieldGeneratorMap(const Descriptor* descriptor, const Options& options); ~FieldGeneratorMap(); const FieldGenerator& get(const FieldDescriptor* field) const; private: const Descriptor* descriptor_; + const Options& options_; google::protobuf::scoped_array<google::protobuf::scoped_ptr<FieldGenerator> > field_generators_; static FieldGenerator* MakeGenerator(const FieldDescriptor* field, diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index d48171b0..385b973e 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -59,6 +59,7 @@ namespace cpp { FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options) : file_(file), + options_(options), message_generators_( new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]), enum_generators_( @@ -66,8 +67,7 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options) service_generators_( new google::protobuf::scoped_ptr<ServiceGenerator>[file->service_count()]), extension_generators_( - new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]), - options_(options) { + new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]) { for (int i = 0; i < file->message_type_count(); i++) { message_generators_[i].reset( @@ -267,12 +267,12 @@ void FileGenerator::GenerateSource(io::Printer* printer) { "right", use_system_include ? ">" : "\""); // Unknown fields implementation in lite mode uses StringOutputStream - if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) { + if (!UseUnknownFieldSet(file_, options_) && file_->message_type_count() > 0) { printer->Print( "#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n"); } - if (HasDescriptorMethods(file_)) { + if (HasDescriptorMethods(file_, options_)) { printer->Print( "#include <google/protobuf/descriptor.h>\n" "#include <google/protobuf/generated_message_reflection.h>\n" @@ -297,7 +297,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) { GenerateNamespaceOpeners(printer); - if (HasDescriptorMethods(file_)) { + if (HasDescriptorMethods(file_, options_)) { printer->Print( "\n" "namespace {\n" @@ -311,7 +311,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) { "name", ClassName(file_->enum_type(i), false)); } - if (HasGenericServices(file_)) { + if (HasGenericServices(file_, options_)) { for (int i = 0; i < file_->service_count(); i++) { printer->Print( "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n", @@ -336,7 +336,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) { // Generate classes. for (int i = 0; i < file_->message_type_count(); i++) { - if (i == 0 && HasGeneratedMethods(file_)) { + if (i == 0 && HasGeneratedMethods(file_, options_)) { printer->Print( "\n" "namespace {\n" @@ -361,7 +361,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) { printer->Print("#endif // PROTOBUF_INLINE_NOT_IN_HEADERS\n"); } - if (HasGenericServices(file_)) { + if (HasGenericServices(file_, options_)) { // Generate services. for (int i = 0; i < file_->service_count(); i++) { if (i == 0) printer->Print("\n"); @@ -462,7 +462,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors() // and we only use AddDescriptors() to allocate default instances. - if (HasDescriptorMethods(file_)) { + if (HasDescriptorMethods(file_, options_)) { printer->Print( "\n" "void $assigndescriptorsname$() {\n", @@ -495,7 +495,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { for (int i = 0; i < file_->enum_type_count(); i++) { enum_generators_[i]->GenerateDescriptorInitializer(printer, i); } - if (HasGenericServices(file_)) { + if (HasGenericServices(file_, options_)) { for (int i = 0; i < file_->service_count(); i++) { service_generators_[i]->GenerateDescriptorInitializer(printer, i); } @@ -561,22 +561,23 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { // Now generate the AddDescriptors() function. PrintHandlingOptionalStaticInitializers( - file_, printer, - // With static initializers. - // Note that we don't need any special synchronization in the following code - // because it is called at static init time before any threads exist. - "void $adddescriptorsname$() {\n" - " static bool already_here = false;\n" - " if (already_here) return;\n" - " already_here = true;\n" - " GOOGLE_PROTOBUF_VERIFY_VERSION;\n" - "\n", - // Without. - "void $adddescriptorsname$_impl() {\n" - " GOOGLE_PROTOBUF_VERIFY_VERSION;\n" - "\n", - // Vars. - "adddescriptorsname", GlobalAddDescriptorsName(file_->name())); + file_, options_, printer, + // With static initializers. + // Note that we don't need any special synchronization in the following + // code + // because it is called at static init time before any threads exist. + "void $adddescriptorsname$() {\n" + " static bool already_here = false;\n" + " if (already_here) return;\n" + " already_here = true;\n" + " GOOGLE_PROTOBUF_VERIFY_VERSION;\n" + "\n", + // Without. + "void $adddescriptorsname$_impl() {\n" + " GOOGLE_PROTOBUF_VERIFY_VERSION;\n" + "\n", + // Vars. + "adddescriptorsname", GlobalAddDescriptorsName(file_->name())); printer->Indent(); @@ -593,7 +594,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { "name", add_desc_name); } - if (HasDescriptorMethods(file_)) { + 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. @@ -687,23 +688,23 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { "\n"); PrintHandlingOptionalStaticInitializers( - file_, printer, - // With static initializers. - "// Force AddDescriptors() to be called at static initialization time.\n" - "struct StaticDescriptorInitializer_$filename$ {\n" - " StaticDescriptorInitializer_$filename$() {\n" - " $adddescriptorsname$();\n" - " }\n" - "} static_descriptor_initializer_$filename$_;\n", - // Without. - "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n" - "void $adddescriptorsname$() {\n" - " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n" - " &$adddescriptorsname$_impl);\n" - "}\n", - // Vars. - "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), - "filename", FilenameIdentifier(file_->name())); + file_, options_, printer, + // With static initializers. + "// Force AddDescriptors() to be called at static initialization time.\n" + "struct StaticDescriptorInitializer_$filename$ {\n" + " StaticDescriptorInitializer_$filename$() {\n" + " $adddescriptorsname$();\n" + " }\n" + "} static_descriptor_initializer_$filename$_;\n", + // Without. + "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n" + "void $adddescriptorsname$() {\n" + " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n" + " &$adddescriptorsname$_impl);\n" + "}\n", + // Vars. + "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), "filename", + FilenameIdentifier(file_->name())); } void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) { @@ -760,16 +761,15 @@ void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer, const string& filename_identifier) { // Generate top of header. printer->Print( - "// 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" - "\n" - "#include <string>\n" - "\n", - "filename", file_->name(), - "filename_identifier", filename_identifier); + "// 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" + "\n" + "#include <string>\n", + "filename", file_->name(), "filename_identifier", filename_identifier); + printer->Print("\n"); } void FileGenerator::GenerateBottomHeaderGuard( @@ -808,12 +808,12 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) { "#include <google/protobuf/arena.h>\n" "#include <google/protobuf/arenastring.h>\n" "#include <google/protobuf/generated_message_util.h>\n"); - if (UseUnknownFieldSet(file_)) { + if (UseUnknownFieldSet(file_, options_)) { printer->Print( "#include <google/protobuf/metadata.h>\n"); } if (file_->message_type_count() > 0) { - if (HasDescriptorMethods(file_)) { + if (HasDescriptorMethods(file_, options_)) { printer->Print( "#include <google/protobuf/message.h>\n"); } else { @@ -827,7 +827,7 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) { if (HasMapFields(file_)) { printer->Print( "#include <google/protobuf/map.h>\n"); - if (HasDescriptorMethods(file_)) { + if (HasDescriptorMethods(file_, options_)) { printer->Print( "#include <google/protobuf/map_field_inl.h>\n"); } else { @@ -837,7 +837,7 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) { } if (HasEnumDefinitions(file_)) { - if (HasDescriptorMethods(file_)) { + if (HasDescriptorMethods(file_, options_)) { printer->Print( "#include <google/protobuf/generated_enum_reflection.h>\n"); } else { @@ -846,12 +846,12 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) { } } - if (HasGenericServices(file_)) { + if (HasGenericServices(file_, options_)) { printer->Print( "#include <google/protobuf/service.h>\n"); } - if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) { + if (UseUnknownFieldSet(file_, options_) && file_->message_type_count() > 0) { printer->Print( "#include <google/protobuf/unknown_field_set.h>\n"); } @@ -955,7 +955,7 @@ void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) { } void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) { - if (HasGenericServices(file_)) { + if (HasGenericServices(file_, options_)) { // Generate service definitions. for (int i = 0; i < file_->service_count(); i++) { if (i > 0) { diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h index ebe990c2..5dcf692b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.h +++ b/src/google/protobuf/compiler/cpp/cpp_file.h @@ -65,8 +65,7 @@ class ExtensionGenerator; // extension.h class FileGenerator { public: // See generator.cc for the meaning of dllexport_decl. - explicit FileGenerator(const FileDescriptor* file, - const Options& options); + FileGenerator(const FileDescriptor* file, const Options& options); ~FileGenerator(); // info_path, if non-empty, should be the path (relative to printer's output) @@ -144,6 +143,7 @@ class FileGenerator { void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer); const FileDescriptor* file_; + const Options options_; google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > message_generators_; google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_; @@ -152,7 +152,6 @@ class FileGenerator { // E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}. vector<string> package_parts_; - const Options options_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); }; diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc index c7aec93a..31d189c2 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.cc +++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc @@ -96,6 +96,8 @@ 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 == "lite") { + file_options.enforce_lite = true; } else { *error = "Unknown generator option: " + options[i].first; return false; @@ -123,7 +125,7 @@ bool CppGenerator::Generate(const FileDescriptor* file, file_generator.GenerateProtoHeader( &printer, file_options.annotate_headers ? info_path : ""); if (file_options.annotate_headers) { - scoped_ptr<io::ZeroCopyOutputStream> info_output( + google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> info_output( generator_context->Open(info_path)); annotations.SerializeToZeroCopyStream(info_output.get()); } @@ -143,7 +145,7 @@ bool CppGenerator::Generate(const FileDescriptor* file, file_generator.GeneratePBHeader( &printer, file_options.annotate_headers ? info_path : ""); if (file_options.annotate_headers) { - scoped_ptr<io::ZeroCopyOutputStream> info_output( + google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> info_output( generator_context->Open(info_path)); annotations.SerializeToZeroCopyStream(info_output.get()); } diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index fb46e387..2ad4d36a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -68,14 +68,15 @@ 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", "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" + "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<string> MakeKeywordsMap() { @@ -171,9 +172,10 @@ string DependentBaseClassTemplateName(const Descriptor* descriptor) { return ClassName(descriptor, false) + "_InternalBase"; } -string SuperClassName(const Descriptor* descriptor) { - return HasDescriptorMethods(descriptor->file()) ? - "::google::protobuf::Message" : "::google::protobuf::MessageLite"; +string SuperClassName(const Descriptor* descriptor, const Options& options) { + return HasDescriptorMethods(descriptor->file(), options) + ? "::google::protobuf::Message" + : "::google::protobuf::MessageLite"; } string DependentBaseDownCast() { @@ -485,8 +487,9 @@ string SafeFunctionName(const Descriptor* descriptor, return function_name; } -bool StaticInitializersForced(const FileDescriptor* file) { - if (HasDescriptorMethods(file) || file->extension_count() > 0) { +bool StaticInitializersForced(const FileDescriptor* file, + const Options& options) { + if (HasDescriptorMethods(file, options) || file->extension_count() > 0) { return true; } for (int i = 0; i < file->message_type_count(); ++i) { @@ -498,10 +501,10 @@ bool StaticInitializersForced(const FileDescriptor* file) { } void PrintHandlingOptionalStaticInitializers( - const FileDescriptor* file, io::Printer* printer, + const FileDescriptor* file, const Options& options, io::Printer* printer, const char* with_static_init, const char* without_static_init, - const char* var1, const string& val1, - const char* var2, const string& val2) { + const char* var1, const string& val1, const char* var2, + const string& val2) { map<string, string> vars; if (var1) { vars[var1] = val1; @@ -510,14 +513,16 @@ void PrintHandlingOptionalStaticInitializers( vars[var2] = val2; } PrintHandlingOptionalStaticInitializers( - vars, file, printer, with_static_init, without_static_init); + vars, file, options, printer, with_static_init, without_static_init); } -void PrintHandlingOptionalStaticInitializers( - const map<string, string>& vars, const FileDescriptor* file, - io::Printer* printer, const char* with_static_init, - const char* without_static_init) { - if (StaticInitializersForced(file)) { +void PrintHandlingOptionalStaticInitializers(const map<string, string>& vars, + const FileDescriptor* file, + const Options& options, + io::Printer* printer, + const char* with_static_init, + const char* without_static_init) { + if (StaticInitializersForced(file, options)) { printer->Print(vars, with_static_init); } else { printer->Print(vars, (string( @@ -612,10 +617,11 @@ enum Utf8CheckMode { }; // Which level of UTF-8 enforcemant is placed on this file. -static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field) { +static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field, + const Options& options) { if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { return STRICT; - } else if (field->file()->options().optimize_for() != + } else if (GetOptimizeFor(field->file(), options) != FileOptions::LITE_RUNTIME) { return VERIFY; } else { @@ -624,13 +630,13 @@ static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field) { } static void GenerateUtf8CheckCode(const FieldDescriptor* field, - bool for_parse, + const Options& options, bool for_parse, const map<string, string>& variables, const char* parameters, const char* strict_function, const char* verify_function, io::Printer* printer) { - switch (GetUtf8CheckMode(field)) { + switch (GetUtf8CheckMode(field, options)) { case STRICT: { if (for_parse) { printer->Print("DO_("); @@ -674,23 +680,22 @@ static void GenerateUtf8CheckCode(const FieldDescriptor* field, } void GenerateUtf8CheckCodeForString(const FieldDescriptor* field, - bool for_parse, + const Options& options, bool for_parse, const map<string, string>& variables, const char* parameters, io::Printer* printer) { - GenerateUtf8CheckCode(field, for_parse, variables, parameters, + GenerateUtf8CheckCode(field, options, for_parse, variables, parameters, "VerifyUtf8String", "VerifyUTF8StringNamedField", printer); } void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field, - bool for_parse, + const Options& options, bool for_parse, const map<string, string>& variables, const char* parameters, io::Printer* printer) { - GenerateUtf8CheckCode(field, for_parse, variables, parameters, - "VerifyUtf8Cord", "VerifyUTF8CordNamedField", - printer); + GenerateUtf8CheckCode(field, options, for_parse, variables, parameters, + "VerifyUtf8Cord", "VerifyUTF8CordNamedField", printer); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index a22d414d..018acfca 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -37,8 +37,9 @@ #include <map> #include <string> -#include <google/protobuf/descriptor.h> +#include <google/protobuf/compiler/cpp/cpp_options.h> #include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/descriptor.h> namespace google { namespace protobuf { @@ -72,7 +73,7 @@ string DependentBaseClassTemplateName(const Descriptor* descriptor); // Name of the base class: either the dependent base class (for use with // proto_h) or google::protobuf::Message. -string SuperClassName(const Descriptor* descriptor); +string SuperClassName(const Descriptor* descriptor, const Options& options); // Returns a string that down-casts from the dependent base class to the // derived class. @@ -118,7 +119,7 @@ string DependentTypeName(const FieldDescriptor* field); string FieldMessageTypeName(const FieldDescriptor* field); // Strips ".proto" or ".protodevel" from the end of a filename. -string StripProto(const string& filename); +LIBPROTOC_EXPORT string StripProto(const string& filename); // 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 @@ -168,12 +169,17 @@ inline bool PreserveUnknownFields(const Descriptor* message) { return message->file()->syntax() != FileDescriptor::SYNTAX_PROTO3; } +// Returns the optimize mode for <file>, respecting <options.enforce_lite>. +::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor( + const FileDescriptor* file, const Options& options); + // If PreserveUnknownFields() is true, determines whether unknown // fields will be stored in an UnknownFieldSet or a string. // If PreserveUnknownFields() is false, this method will not be // used. -inline bool UseUnknownFieldSet(const FileDescriptor* file) { - return file->options().optimize_for() != FileOptions::LITE_RUNTIME; +inline bool UseUnknownFieldSet(const FileDescriptor* file, + const Options& options) { + return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME; } @@ -186,45 +192,52 @@ bool HasEnumDefinitions(const FileDescriptor* file); // Does this file have generated parsing, serialization, and other // standard methods for which reflection-based fallback implementations exist? -inline bool HasGeneratedMethods(const FileDescriptor* file) { - return file->options().optimize_for() != FileOptions::CODE_SIZE; +inline bool HasGeneratedMethods(const FileDescriptor* file, + const Options& options) { + return GetOptimizeFor(file, options) != FileOptions::CODE_SIZE; } // Do message classes in this file have descriptor and reflection methods? -inline bool HasDescriptorMethods(const FileDescriptor* file) { - return file->options().optimize_for() != FileOptions::LITE_RUNTIME; +inline bool HasDescriptorMethods(const FileDescriptor* file, + const Options& options) { + return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME; } // Should we generate generic services for this file? -inline bool HasGenericServices(const FileDescriptor* file) { +inline bool HasGenericServices(const FileDescriptor* file, + const Options& options) { return file->service_count() > 0 && - file->options().optimize_for() != FileOptions::LITE_RUNTIME && + GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME && 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) { - return file->options().optimize_for() == FileOptions::SPEED; +inline bool HasFastArraySerialization(const FileDescriptor* file, + const Options& options) { + return GetOptimizeFor(file, options) == FileOptions::SPEED; } // Returns whether we have to generate code with static initializers. -bool StaticInitializersForced(const FileDescriptor* file); +bool StaticInitializersForced(const FileDescriptor* file, + const Options& options); // Prints 'with_static_init' if static initializers have to be used for the // provided file. Otherwise emits both 'with_static_init' and // 'without_static_init' using #ifdef. void PrintHandlingOptionalStaticInitializers( - const FileDescriptor* file, io::Printer* printer, + const FileDescriptor* file, const Options& options, io::Printer* printer, const char* with_static_init, const char* without_static_init, - const char* var1 = NULL, const string& val1 = "", - const char* var2 = NULL, const string& val2 = ""); + const char* var1 = NULL, const string& val1 = "", const char* var2 = NULL, + const string& val2 = ""); -void PrintHandlingOptionalStaticInitializers( - const map<string, string>& vars, const FileDescriptor* file, - io::Printer* printer, const char* with_static_init, - const char* without_static_init); +void PrintHandlingOptionalStaticInitializers(const map<string, string>& vars, + const FileDescriptor* file, + const Options& options, + io::Printer* printer, + const char* with_static_init, + const char* without_static_init); inline bool IsMapEntryMessage(const Descriptor* descriptor) { @@ -267,19 +280,23 @@ bool IsAnyMessage(const Descriptor* descriptor); bool IsWellKnownMessage(const FileDescriptor* descriptor); -void GenerateUtf8CheckCodeForString( - const FieldDescriptor* field, - bool for_parse, - const map<string, string>& variables, - const char* parameters, - io::Printer* printer); - -void GenerateUtf8CheckCodeForCord( - const FieldDescriptor* field, - bool for_parse, - const map<string, string>& variables, - const char* parameters, - io::Printer* printer); +void GenerateUtf8CheckCodeForString(const FieldDescriptor* field, + const Options& options, bool for_parse, + const map<string, string>& variables, + const char* parameters, + io::Printer* printer); + +void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field, + const Options& options, bool for_parse, + const map<string, string>& variables, + const char* parameters, io::Printer* printer); + +inline ::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor( + const FileDescriptor* file, const Options& options) { + return options.enforce_lite + ? FileOptions::LITE_RUNTIME + : file->options().optimize_for(); +} } // namespace cpp } // namespace compiler diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc index e5e2f07d..f585c31b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc @@ -49,10 +49,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor, const Options& options) { SetCommonFieldVariables(descriptor, variables, options); (*variables)["type"] = FieldMessageTypeName(descriptor); - (*variables)["stream_writer"] = (*variables)["declared_type"] + - (HasFastArraySerialization(descriptor->message_type()->file()) ? - "MaybeToArray" : - ""); + (*variables)["stream_writer"] = + (*variables)["declared_type"] + + (HasFastArraySerialization(descriptor->message_type()->file(), options) + ? "MaybeToArray" + : ""); (*variables)["full_name"] = descriptor->full_name(); const FieldDescriptor* key = @@ -83,7 +84,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["number"] = SimpleItoa(descriptor->number()); (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); - if (HasDescriptorMethods(descriptor->file())) { + if (HasDescriptorMethods(descriptor->file(), options)) { (*variables)["lite"] = ""; } else { (*variables)["lite"] = "Lite"; @@ -98,10 +99,10 @@ void SetMessageVariables(const FieldDescriptor* descriptor, } } -MapFieldGenerator:: -MapFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : descriptor_(descriptor), +MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : FieldGenerator(options), + descriptor_(descriptor), dependent_field_(options.proto_h && IsFieldDependent(descriptor)) { SetMessageVariables(descriptor, &variables_, options); } @@ -127,10 +128,10 @@ GeneratePrivateMembers(io::Printer* printer) const { void MapFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n" - " $name$() const$deprecation$;\n" - "::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n" - " mutable_$name$()$deprecation$;\n"); + "$deprecated_attr$const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n" + " $name$() const;\n" + "$deprecated_attr$::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n" + " mutable_$name$();\n"); } void MapFieldGenerator:: @@ -170,7 +171,7 @@ GenerateSwappingCode(io::Printer* printer) const { void MapFieldGenerator:: GenerateConstructorCode(io::Printer* printer) const { - if (HasDescriptorMethods(descriptor_->file())) { + if (HasDescriptorMethods(descriptor_->file(), options_)) { printer->Print(variables_, "$name$_.SetAssignDescriptorCallback(\n" " protobuf_AssignDescriptorsOnce);\n" @@ -217,7 +218,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { " (*mutable_$name$())[entry->key()] =\n" " static_cast< $val_cpp$ >(*entry->mutable_value());\n" " } else {\n"); - if (HasDescriptorMethods(descriptor_->file())) { + if (HasDescriptorMethods(descriptor_->file(), options_)) { printer->Print(variables_, " mutable_unknown_fields()" "->AddLengthDelimited($number$, data);\n"); @@ -238,14 +239,14 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { descriptor_->message_type()->FindFieldByName("key"); if (key_field->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - key_field, true, variables_, + key_field, options_, true, variables_, "entry->key().data(), entry->key().length(),\n", printer); } if (value_field->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString( - value_field, true, variables_, - "entry->mutable_value()->data(),\n" - "entry->mutable_value()->length(),\n", printer); + GenerateUtf8CheckCodeForString(value_field, options_, true, variables_, + "entry->mutable_value()->data(),\n" + "entry->mutable_value()->length(),\n", + printer); } // If entry is allocated by arena, its desctructor should be avoided. @@ -285,14 +286,14 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { const FieldDescriptor* value_field = descriptor_->message_type()->FindFieldByName("value"); if (key_field->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString( - key_field, false, variables_, - "it->first.data(), it->first.length(),\n", printer); + GenerateUtf8CheckCodeForString(key_field, options_, false, variables_, + "it->first.data(), it->first.length(),\n", + printer); } if (value_field->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString( - value_field, false, variables_, - "it->second.data(), it->second.length(),\n", printer); + GenerateUtf8CheckCodeForString(value_field, options_, false, variables_, + "it->second.data(), it->second.length(),\n", + printer); } printer->Outdent(); @@ -343,14 +344,14 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { const FieldDescriptor* value_field = descriptor_->message_type()->FindFieldByName("value"); if (key_field->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString( - key_field, false, variables_, - "it->first.data(), it->first.length(),\n", printer); + GenerateUtf8CheckCodeForString(key_field, options_, false, variables_, + "it->first.data(), it->first.length(),\n", + printer); } if (value_field->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString( - value_field, false, variables_, - "it->second.data(), it->second.length(),\n", printer); + GenerateUtf8CheckCodeForString(value_field, options_, false, variables_, + "it->second.data(), it->second.length(),\n", + printer); } printer->Outdent(); diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h index 5e205623..087dcde0 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h @@ -43,8 +43,7 @@ namespace cpp { class MapFieldGenerator : public FieldGenerator { public: - explicit MapFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options); ~MapFieldGenerator(); // implements FieldGenerator --------------------------------------- diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index c3166611..da2a4c92 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -106,8 +106,8 @@ struct ExtensionRangeSorter { // Returns true if the "required" restriction check should be ignored for the // given field. -inline static bool ShouldIgnoreRequiredFieldCheck( - const FieldDescriptor* field) { +inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field, + const Options& options) { return false; } @@ -116,9 +116,8 @@ inline static bool ShouldIgnoreRequiredFieldCheck( // // already_seen is used to avoid checking the same type multiple times // (and also to protect against recursion). -static bool HasRequiredFields( - const Descriptor* type, - hash_set<const Descriptor*>* already_seen) { +static bool HasRequiredFields(const Descriptor* type, const Options& options, + hash_set<const Descriptor*>* already_seen) { if (already_seen->count(type) > 0) { // Since the first occurrence of a required field causes the whole // function to return true, we can assume that if the type is already @@ -138,8 +137,8 @@ static bool HasRequiredFields( return true; } if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && - !ShouldIgnoreRequiredFieldCheck(field)) { - if (HasRequiredFields(field->message_type(), already_seen)) { + !ShouldIgnoreRequiredFieldCheck(field, options)) { + if (HasRequiredFields(field->message_type(), options, already_seen)) { return true; } } @@ -148,9 +147,9 @@ static bool HasRequiredFields( return false; } -static bool HasRequiredFields(const Descriptor* type) { +static bool HasRequiredFields(const Descriptor* type, const Options& options) { hash_set<const Descriptor*> already_seen; - return HasRequiredFields(type, &already_seen); + return HasRequiredFields(type, options, &already_seen); } // This returns an estimate of the compiler's alignment for the field. This @@ -480,7 +479,7 @@ GenerateDependentFieldAccessorDeclarations(io::Printer* printer) { // 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, "void clear_$name$()$deprecation$;\n"); + printer->Print(vars, "$deprecated_attr$void clear_$name$();\n"); } // Generate type-specific accessor declarations. field_generators_.get(field).GenerateDependentAccessorDeclarations(printer); @@ -515,22 +514,24 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { } if (field->is_repeated()) { - printer->Print(vars, "int $name$_size() const$deprecation$;\n"); + printer->Print(vars, "$deprecated_attr$int $name$_size() const;\n"); } else if (HasHasMethod(field)) { - printer->Print(vars, "bool has_$name$() const$deprecation$;\n"); + printer->Print(vars, "$deprecated_attr$bool has_$name$() const;\n"); } else if (HasPrivateHasMethod(field)) { printer->Print(vars, "private:\n" - "bool has_$name$() const$deprecation$;\n" + "bool has_$name$() const;\n" "public:\n"); } if (!dependent_field) { // If this field is dependent, then its clear_() method is in the // depenent base class. (See also GenerateDependentAccessorDeclarations.) - printer->Print(vars, "void clear_$name$()$deprecation$;\n"); + printer->Print(vars, "$deprecated_attr$void clear_$name$();\n"); } - printer->Print(vars, "static const int $constant_name$ = $number$;\n"); + printer->Print(vars, + "$deprecated_attr$static const int $constant_name$ = " + "$number$;\n"); // Generate type-specific accessor declarations. field_generators_.get(field).GenerateAccessorDeclarations(printer); @@ -837,7 +838,7 @@ GenerateDependentBaseClassDefinition(io::Printer* printer) { map<string, string> vars; vars["classname"] = DependentBaseClassTemplateName(descriptor_); - vars["superclass"] = SuperClassName(descriptor_); + vars["superclass"] = SuperClassName(descriptor_, options_); printer->Print(vars, "template <class T>\n" @@ -888,7 +889,7 @@ GenerateClassDefinition(io::Printer* printer) { vars["superclass"] = DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">"; } else { - vars["superclass"] = SuperClassName(descriptor_); + vars["superclass"] = SuperClassName(descriptor_, options_); } printer->Print(vars, "class $dllexport$$classname$ : public $superclass$ {\n"); @@ -912,7 +913,7 @@ GenerateClassDefinition(io::Printer* printer) { "\n"); if (PreserveUnknownFields(descriptor_)) { - if (UseUnknownFieldSet(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print( "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n" " return _internal_metadata_.unknown_fields();\n" @@ -966,7 +967,7 @@ GenerateClassDefinition(io::Printer* printer) { } // Only generate this member if it's not disabled. - if (HasDescriptorMethods(descriptor_->file()) && + if (HasDescriptorMethods(descriptor_->file(), options_) && !descriptor_->options().no_standard_descriptor_accessor()) { printer->Print(vars, "static const ::google::protobuf::Descriptor* descriptor();\n"); @@ -1003,7 +1004,7 @@ GenerateClassDefinition(io::Printer* printer) { "\n"); } - if (!StaticInitializersForced(descriptor_->file())) { + if (!StaticInitializersForced(descriptor_->file(), options_)) { printer->Print(vars, "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n" "// Returns the internal default instance pointer. This function can\n" @@ -1046,8 +1047,8 @@ GenerateClassDefinition(io::Printer* printer) { "\n" "$classname$* New(::google::protobuf::Arena* arena) const;\n"); - if (HasGeneratedMethods(descriptor_->file())) { - if (HasDescriptorMethods(descriptor_->file())) { + if (HasGeneratedMethods(descriptor_->file(), options_)) { + if (HasDescriptorMethods(descriptor_->file(), options_)) { printer->Print(vars, "void CopyFrom(const ::google::protobuf::Message& from);\n" "void MergeFrom(const ::google::protobuf::Message& from);\n"); @@ -1069,11 +1070,11 @@ GenerateClassDefinition(io::Printer* printer) { " ::google::protobuf::io::CodedOutputStream* output) const;\n"); // DiscardUnknownFields() is implemented in message.cc using reflections. We // need to implement this function in generated code for messages. - if (!UseUnknownFieldSet(descriptor_->file())) { + if (!UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print( "void DiscardUnknownFields();\n"); } - if (HasFastArraySerialization(descriptor_->file())) { + if (HasFastArraySerialization(descriptor_->file(), options_)) { printer->Print( "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n"); } @@ -1096,7 +1097,7 @@ GenerateClassDefinition(io::Printer* printer) { } uses_string_ = false; if (PreserveUnknownFields(descriptor_) && - !UseUnknownFieldSet(descriptor_->file())) { + !UseUnknownFieldSet(descriptor_->file(), options_)) { uses_string_ = true; } for (int i = 0; i < descriptors.size(); i++) { @@ -1126,7 +1127,7 @@ GenerateClassDefinition(io::Printer* printer) { "classname", classname_); } - if (UseUnknownFieldSet(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print( "private:\n" "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n" @@ -1150,7 +1151,7 @@ GenerateClassDefinition(io::Printer* printer) { "\n"); } - if (HasDescriptorMethods(descriptor_->file())) { + if (HasDescriptorMethods(descriptor_->file(), options_)) { printer->Print( "::google::protobuf::Metadata GetMetadata() const;\n" "\n"); @@ -1239,7 +1240,7 @@ GenerateClassDefinition(io::Printer* printer) { "oneof_name", descriptor_->oneof_decl(i)->name()); } - if (HasGeneratedMethods(descriptor_->file()) && + if (HasGeneratedMethods(descriptor_->file(), options_) && !descriptor_->options().message_set_wire_format() && num_required_fields_ > 1) { printer->Print( @@ -1281,7 +1282,7 @@ GenerateClassDefinition(io::Printer* printer) { "\n"); } - if (UseUnknownFieldSet(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print( "::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;\n"); } else { @@ -1408,15 +1409,14 @@ GenerateClassDefinition(io::Printer* printer) { // friends so that they can access private static variables like // default_instance_ and reflection_. PrintHandlingOptionalStaticInitializers( - descriptor_->file(), printer, - // With static initializers. - "friend void $dllexport_decl$ $adddescriptorsname$();\n", - // Without. - "friend void $dllexport_decl$ $adddescriptorsname$_impl();\n", - // Vars. - "dllexport_decl", options_.dllexport_decl, - "adddescriptorsname", - GlobalAddDescriptorsName(descriptor_->file()->name())); + descriptor_->file(), options_, printer, + // With static initializers. + "friend void $dllexport_decl$ $adddescriptorsname$();\n", + // Without. + "friend void $dllexport_decl$ $adddescriptorsname$_impl();\n", + // Vars. + "dllexport_decl", options_.dllexport_decl, "adddescriptorsname", + GlobalAddDescriptorsName(descriptor_->file()->name())); printer->Print( "friend void $assigndescriptorsname$();\n" @@ -1579,7 +1579,7 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) { // Unknown field offset: either points to the unknown field set if embedded // directly, or indicates that the unknown field set is stored as part of the // internal metadata if not. - if (UseUnknownFieldSet(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print(vars, " -1,\n"); } else { @@ -1619,7 +1619,7 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) { // arena pointer and unknown field set (in a space-efficient way) if we use // that implementation strategy, or an offset directly to the arena pointer if // not (because e.g. we don't have an unknown field set). - if (UseUnknownFieldSet(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print(vars, " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" "$classname$, _internal_metadata_),\n"); @@ -1709,7 +1709,7 @@ GenerateDefaultInstanceAllocator(io::Printer* printer) { "classname", classname_); if ((descriptor_->oneof_decl_count() > 0) && - HasDescriptorMethods(descriptor_->file())) { + HasDescriptorMethods(descriptor_->file(), options_)) { printer->Print( "$classname$_default_oneof_instance_ = new $classname$OneofInstance();\n", "classname", classname_); @@ -1749,7 +1749,7 @@ GenerateShutdownCode(io::Printer* printer) { "delete $classname$::default_instance_;\n", "classname", classname_); - if (HasDescriptorMethods(descriptor_->file())) { + if (HasDescriptorMethods(descriptor_->file(), options_)) { if (descriptor_->oneof_decl_count() > 0) { printer->Print( "delete $classname$_default_oneof_instance_;\n", @@ -1777,7 +1777,8 @@ void MessageGenerator:: GenerateClassMethods(io::Printer* printer) { // mutable_unknown_fields wrapper function for LazyStringOutputStream // callback. - if (!UseUnknownFieldSet(descriptor_->file())) { + if (PreserveUnknownFields(descriptor_) && + !UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print( "static ::std::string* MutableUnknownFieldsFor$classname$(\n" " $classname$* ptr) {\n" @@ -1851,7 +1852,7 @@ GenerateClassMethods(io::Printer* printer) { printer->Print("\n"); } - if (HasGeneratedMethods(descriptor_->file())) { + if (HasGeneratedMethods(descriptor_->file(), options_)) { GenerateClear(printer); printer->Print("\n"); @@ -1861,7 +1862,7 @@ GenerateClassMethods(io::Printer* printer) { GenerateSerializeWithCachedSizes(printer); printer->Print("\n"); - if (HasFastArraySerialization(descriptor_->file())) { + if (HasFastArraySerialization(descriptor_->file(), options_)) { GenerateSerializeWithCachedSizesToArray(printer); printer->Print("\n"); } @@ -1882,7 +1883,7 @@ GenerateClassMethods(io::Printer* printer) { GenerateSwap(printer); printer->Print("\n"); - if (HasDescriptorMethods(descriptor_->file())) { + if (HasDescriptorMethods(descriptor_->file(), options_)) { printer->Print( "::google::protobuf::Metadata $classname$::GetMetadata() const {\n" " protobuf_AssignDescriptorsOnce();\n" @@ -1959,7 +1960,7 @@ GenerateSharedConstructorCode(io::Printer* printer) { "_cached_size_ = 0;\n").c_str()); if (PreserveUnknownFields(descriptor_) && - !UseUnknownFieldSet(descriptor_->file())) { + !UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print( "_unknown_fields_.UnsafeSetDefault(\n" " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"); @@ -2004,7 +2005,7 @@ GenerateSharedDestructorCode(io::Printer* printer) { // Write the desctructor for _unknown_fields_ in lite runtime. if (PreserveUnknownFields(descriptor_) && - !UseUnknownFieldSet(descriptor_->file())) { + !UseUnknownFieldSet(descriptor_->file(), options_)) { if (SupportsArenas(descriptor_)) { printer->Print( "_unknown_fields_.Destroy(\n" @@ -2035,11 +2036,11 @@ GenerateSharedDestructorCode(io::Printer* printer) { } PrintHandlingOptionalStaticInitializers( - descriptor_->file(), printer, - // With static initializers. - "if (this != default_instance_) {\n", - // Without. - "if (this != &default_instance()) {\n"); + descriptor_->file(), options_, printer, + // With static initializers. + "if (this != default_instance_) {\n", + // Without. + "if (this != &default_instance()) {\n"); // We need to delete all embedded messages. // TODO(kenton): If we make unset messages point at default instances @@ -2119,7 +2120,7 @@ GenerateStructors(io::Printer* printer) { superclass = DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">"; } else { - superclass = SuperClassName(descriptor_); + superclass = SuperClassName(descriptor_, options_); } string initializer_with_arena = superclass + "()"; @@ -2127,7 +2128,7 @@ GenerateStructors(io::Printer* printer) { initializer_with_arena += ",\n _extensions_(arena)"; } - if (UseUnknownFieldSet(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { initializer_with_arena += ",\n _internal_metadata_(arena)"; } else { initializer_with_arena += ",\n _arena_ptr_(arena)"; @@ -2147,7 +2148,7 @@ GenerateStructors(io::Printer* printer) { } string initializer_null; - initializer_null = (UseUnknownFieldSet(descriptor_->file()) ? + initializer_null = (UseUnknownFieldSet(descriptor_->file(), options_) ? ", _internal_metadata_(NULL)" : ", _arena_ptr_(NULL)"); if (IsAnyMessage(descriptor_)) { initializer_null += ", _any_metadata_(&type_url_, &value_)"; @@ -2201,24 +2202,23 @@ GenerateStructors(io::Printer* printer) { if (!field->is_repeated() && field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && (field->containing_oneof() == NULL || - HasDescriptorMethods(descriptor_->file()))) { + HasDescriptorMethods(descriptor_->file(), options_))) { string name; if (field->containing_oneof()) { name = classname_ + "_default_oneof_instance_->"; } name += FieldName(field); PrintHandlingOptionalStaticInitializers( - descriptor_->file(), printer, - // With static initializers. - " $name$_ = const_cast< $type$*>(&$type$::default_instance());\n", - // Without. - " $name$_ = const_cast< $type$*>(\n" - " $type$::internal_default_instance());\n", - // Vars. - "name", name, - "type", FieldMessageTypeName(field)); + descriptor_->file(), options_, printer, + // With static initializers. + " $name$_ = const_cast< $type$*>(&$type$::default_instance());\n", + // Without. + " $name$_ = const_cast< $type$*>(\n" + " $type$::internal_default_instance());\n", + // Vars. + "name", name, "type", FieldMessageTypeName(field)); } else if (field->containing_oneof() && - HasDescriptorMethods(descriptor_->file())) { + HasDescriptorMethods(descriptor_->file(), options_)) { field_generators_.get(descriptor_->field(i)) .GenerateConstructorCode(printer); } @@ -2234,10 +2234,10 @@ GenerateStructors(io::Printer* printer) { "classname", classname_, "superclass", superclass, "full_name", descriptor_->full_name()); - if (UseUnknownFieldSet(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print( ",\n _internal_metadata_(NULL)"); - } else if (!UseUnknownFieldSet(descriptor_->file())) { + } else if (!UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print(",\n _arena_ptr_(NULL)"); } if (IsAnyMessage(descriptor_)) { @@ -2285,7 +2285,7 @@ GenerateStructors(io::Printer* printer) { "classname", classname_); // Only generate this member if it's not disabled. - if (HasDescriptorMethods(descriptor_->file()) && + if (HasDescriptorMethods(descriptor_->file(), options_) && !descriptor_->options().no_standard_descriptor_accessor()) { printer->Print( "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n" @@ -2303,14 +2303,14 @@ GenerateStructors(io::Printer* printer) { "classname", classname_); PrintHandlingOptionalStaticInitializers( - descriptor_->file(), printer, - // With static initializers. - " if (default_instance_ == NULL) $adddescriptorsname$();\n", - // Without. - " $adddescriptorsname$();\n", - // Vars. - "adddescriptorsname", - GlobalAddDescriptorsName(descriptor_->file()->name())); + descriptor_->file(), options_, printer, + // With static initializers. + " if (default_instance_ == NULL) $adddescriptorsname$();\n", + // Without. + " $adddescriptorsname$();\n", + // Vars. + "adddescriptorsname", + GlobalAddDescriptorsName(descriptor_->file()->name())); printer->Print( " return *default_instance_;\n" @@ -2352,8 +2352,10 @@ static int popcnt(uint32 n) { void MessageGenerator:: GenerateClear(io::Printer* printer) { - printer->Print("void $classname$::Clear() {\n", - "classname", classname_); + printer->Print( + "void $classname$::Clear() {\n" + "// @@protoc_insertion_point(message_clear_start:$full_name$)\n", + "classname", classname_, "full_name", descriptor_->full_name()); printer->Indent(); // Step 1: Extensions @@ -2390,8 +2392,16 @@ GenerateClear(io::Printer* printer) { // positions of two fields in the Message. // ZR_ zeroes a non-empty range of fields via memset. const char* macros = + "#if defined(__clang__)\n" + "#define ZR_HELPER_(f) \\\n" + " _Pragma(\"clang diagnostic push\") \\\n" + " _Pragma(\"clang diagnostic ignored \\\"-Winvalid-offsetof\\\"\") \\\n" + " __builtin_offsetof($classname$, f) \\\n" + " _Pragma(\"clang diagnostic pop\")\n" + "#else\n" "#define ZR_HELPER_(f) reinterpret_cast<char*>(\\\n" - " &reinterpret_cast<$classname$*>(16)->f)\n\n" + " &reinterpret_cast<$classname$*>(16)->f)\n" + "#endif\n\n" "#define ZR_(first, last) do {\\\n" " ::memset(&first, 0,\\\n" " ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\\\n" @@ -2519,7 +2529,7 @@ GenerateClear(io::Printer* printer) { } if (PreserveUnknownFields(descriptor_)) { - if (UseUnknownFieldSet(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print( "if (_internal_metadata_.have_unknown_fields()) {\n" " mutable_unknown_fields()->Clear();\n" @@ -2549,10 +2559,13 @@ GenerateOneofClear(io::Printer* printer) { map<string, string> 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"); + "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"); @@ -2635,7 +2648,7 @@ GenerateSwap(io::Printer* printer) { "classname", classname_); printer->Indent(); - if (HasGeneratedMethods(descriptor_->file())) { + if (HasGeneratedMethods(descriptor_->file(), options_)) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); field_generators_.get(field).GenerateSwappingCode(printer); @@ -2656,19 +2669,15 @@ GenerateSwap(io::Printer* printer) { } } - if (PreserveUnknownFields(descriptor_)) { - if (UseUnknownFieldSet(descriptor_->file())) { - printer->Print( + // Ignore PreserveUnknownFields here - always swap internal_metadata as it + // may contain more than just unknown fields. + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print( "_internal_metadata_.Swap(&other->_internal_metadata_);\n"); - } else { - printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n"); - } } else { - // Still swap internal_metadata as it may contain more than just - // unknown fields. - printer->Print( - "_internal_metadata_.Swap(&other->_internal_metadata_);\n"); + printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n"); } + printer->Print("std::swap(_cached_size_, other->_cached_size_);\n"); if (descriptor_->extension_range_count() > 0) { printer->Print("_extensions_.Swap(&other->_extensions_);\n"); @@ -2683,13 +2692,15 @@ GenerateSwap(io::Printer* printer) { void MessageGenerator:: GenerateMergeFrom(io::Printer* printer) { - if (HasDescriptorMethods(descriptor_->file())) { + 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" - " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n", - "classname", classname_); + "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n" + "// @@protoc_insertion_point(generalized_merge_from_start:" + "$full_name$)\n" + " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n", + "classname", classname_, "full_name", descriptor_->full_name()); printer->Indent(); // Cast the message to the proper type. If we find that the message is @@ -2701,11 +2712,15 @@ GenerateMergeFrom(io::Printer* printer) { " ::google::protobuf::internal::DynamicCastToGenerated<const $classname$>(\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_); + "classname", classname_, "full_name", descriptor_->full_name()); printer->Outdent(); printer->Print("}\n\n"); @@ -2722,9 +2737,11 @@ GenerateMergeFrom(io::Printer* printer) { // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast. printer->Print( - "void $classname$::MergeFrom(const $classname$& from) {\n" - " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n", - "classname", classname_); + "void $classname$::MergeFrom(const $classname$& from) {\n" + "// @@protoc_insertion_point(class_specific_merge_from_start:" + "$full_name$)\n" + " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n", + "classname", classname_, "full_name", descriptor_->full_name()); printer->Indent(); // Merge Repeated fields. These fields do not require a @@ -2825,7 +2842,7 @@ GenerateMergeFrom(io::Printer* printer) { } if (PreserveUnknownFields(descriptor_)) { - if (UseUnknownFieldSet(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print( "if (from._internal_metadata_.have_unknown_fields()) {\n" " mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n" @@ -2844,12 +2861,14 @@ GenerateMergeFrom(io::Printer* printer) { void MessageGenerator:: GenerateCopyFrom(io::Printer* printer) { - if (HasDescriptorMethods(descriptor_->file())) { + 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", - "classname", classname_); + "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n" + "// @@protoc_insertion_point(generalized_copy_from_start:" + "$full_name$)\n", + "classname", classname_, "full_name", descriptor_->full_name()); printer->Indent(); printer->Print( @@ -2863,8 +2882,10 @@ GenerateCopyFrom(io::Printer* printer) { // Generate the class-specific CopyFrom. printer->Print( - "void $classname$::CopyFrom(const $classname$& from) {\n", - "classname", classname_); + "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( @@ -2886,15 +2907,15 @@ GenerateMergeFromCodedStream(io::Printer* printer) { "classname", classname_); PrintHandlingOptionalStaticInitializers( - descriptor_->file(), printer, - // With static initializers. - " return _extensions_.ParseMessageSet(input, default_instance_,\n" - " mutable_unknown_fields());\n", - // Without. - " return _extensions_.ParseMessageSet(input, &default_instance(),\n" - " mutable_unknown_fields());\n", - // Vars. - "classname", classname_); + descriptor_->file(), options_, printer, + // With static initializers. + " return _extensions_.ParseMessageSet(input, default_instance_,\n" + " mutable_unknown_fields());\n", + // Without. + " return _extensions_.ParseMessageSet(input, &default_instance(),\n" + " mutable_unknown_fields());\n", + // Vars. + "classname", classname_); printer->Print( "}\n"); @@ -2904,17 +2925,18 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Print( "bool $classname$::MergePartialFromCodedStream(\n" " ::google::protobuf::io::CodedInputStream* input) {\n" - "#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure\n" + "#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure\n" " ::google::protobuf::uint32 tag;\n", "classname", classname_); - if (!UseUnknownFieldSet(descriptor_->file())) { + if (PreserveUnknownFields(descriptor_) && + !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::internal::NewPermanentCallback(\n" + " ::google::protobuf::internal::NewPermanentCallback(\n" " &MutableUnknownFieldsFor$classname$, this));\n" " ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n" " &unknown_fields_string, false);\n", @@ -3136,32 +3158,32 @@ GenerateMergeFromCodedStream(io::Printer* printer) { } printer->Print(") {\n"); if (PreserveUnknownFields(descriptor_)) { - if (UseUnknownFieldSet(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { PrintHandlingOptionalStaticInitializers( - descriptor_->file(), printer, - // With static initializers. - " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" - " mutable_unknown_fields()));\n", - // Without. - " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n" - " mutable_unknown_fields()));\n"); + descriptor_->file(), options_, printer, + // With static initializers. + " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" + " mutable_unknown_fields()));\n", + // Without. + " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n" + " mutable_unknown_fields()));\n"); } else { PrintHandlingOptionalStaticInitializers( - descriptor_->file(), printer, - // With static initializers. - " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" - " &unknown_fields_stream));\n", - // Without. - " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n" - " &unknown_fields_stream));\n"); + descriptor_->file(), options_, printer, + // With static initializers. + " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" + " &unknown_fields_stream));\n", + // Without. + " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n" + " &unknown_fields_stream));\n"); } } else { PrintHandlingOptionalStaticInitializers( - descriptor_->file(), printer, - // With static initializers. - " DO_(_extensions_.ParseField(tag, input, default_instance_);\n", - // Without. - " DO_(_extensions_.ParseField(tag, input, &default_instance());\n"); + descriptor_->file(), options_, printer, + // With static initializers. + " DO_(_extensions_.ParseField(tag, input, default_instance_);\n", + // Without. + " DO_(_extensions_.ParseField(tag, input, &default_instance());\n"); } printer->Print( " continue;\n" @@ -3170,7 +3192,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // We really don't recognize this tag. Skip it. if (PreserveUnknownFields(descriptor_)) { - if (UseUnknownFieldSet(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print( "DO_(::google::protobuf::internal::WireFormat::SkipField(\n" " input, tag, mutable_unknown_fields()));\n"); @@ -3263,7 +3285,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) { " ::google::protobuf::io::CodedOutputStream* output) const {\n" " _extensions_.SerializeMessageSetWithCachedSizes(output);\n", "classname", classname_); - GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file())); + GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); printer->Print( " ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n" " unknown_fields(), output);\n"); @@ -3303,7 +3325,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { " target =\n" " _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n", "classname", classname_); - GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file())); + GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); printer->Print( " target = ::google::protobuf::internal::WireFormat::\n" " SerializeUnknownMessageSetItemsToArray(\n" @@ -3369,7 +3391,7 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { } if (PreserveUnknownFields(descriptor_)) { - if (UseUnknownFieldSet(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print("if (_internal_metadata_.have_unknown_fields()) {\n"); printer->Indent(); if (to_array) { @@ -3436,10 +3458,11 @@ GenerateByteSize(io::Printer* printer) { if (descriptor_->options().message_set_wire_format()) { // Special-case MessageSet. printer->Print( - "int $classname$::ByteSize() const {\n" - " int total_size = _extensions_.MessageSetByteSize();\n", - "classname", classname_); - GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file())); + "int $classname$::ByteSize() const {\n" + "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n" + " int total_size = _extensions_.MessageSetByteSize();\n", + "classname", classname_, "full_name", descriptor_->full_name()); + GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); printer->Print( "if (_internal_metadata_.have_unknown_fields()) {\n" " total_size += ::google::protobuf::internal::WireFormat::\n" @@ -3458,8 +3481,10 @@ GenerateByteSize(io::Printer* printer) { // Emit a function (rarely used, we hope) that handles the required fields // by checking for each one individually. printer->Print( - "int $classname$::RequiredFieldsByteSizeFallback() const {\n", - "classname", classname_); + "int $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("int total_size = 0;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { @@ -3482,8 +3507,9 @@ GenerateByteSize(io::Printer* printer) { } printer->Print( - "int $classname$::ByteSize() const {\n", - "classname", classname_); + "int $classname$::ByteSize() const {\n" + "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n", + "classname", classname_, "full_name", descriptor_->full_name()); printer->Indent(); printer->Print( "int total_size = 0;\n" @@ -3659,7 +3685,7 @@ GenerateByteSize(io::Printer* printer) { } if (PreserveUnknownFields(descriptor_)) { - if (UseUnknownFieldSet(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print( "if (_internal_metadata_.have_unknown_fields()) {\n" " total_size +=\n" @@ -3725,8 +3751,8 @@ GenerateIsInitialized(io::Printer* printer) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && - !ShouldIgnoreRequiredFieldCheck(field) && - HasRequiredFields(field->message_type())) { + !ShouldIgnoreRequiredFieldCheck(field, options_) && + HasRequiredFields(field->message_type(), options_)) { if (field->is_repeated()) { printer->Print( "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))" diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc index b4545892..332c0264 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -53,10 +53,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["non_null_ptr_to_name"] = StrCat("this->", (*variables)["name"], "_"); } - (*variables)["stream_writer"] = (*variables)["declared_type"] + - (HasFastArraySerialization(descriptor->message_type()->file()) ? - "MaybeToArray" : - ""); + (*variables)["stream_writer"] = + (*variables)["declared_type"] + + (HasFastArraySerialization(descriptor->message_type()->file(), options) + ? "MaybeToArray" + : ""); // NOTE: Escaped here to unblock proto1->proto2 migration. // TODO(liujisi): Extend this to apply for other conflicting methods. (*variables)["release_name"] = @@ -77,11 +78,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor, // =================================================================== -MessageFieldGenerator:: -MessageFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : descriptor_(descriptor), - dependent_field_(options.proto_h && IsFieldDependent(descriptor)) { +MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : FieldGenerator(options), + descriptor_(descriptor), + dependent_field_(options.proto_h && IsFieldDependent(descriptor)) { SetMessageVariables(descriptor, &variables_, options); } @@ -95,7 +96,7 @@ GeneratePrivateMembers(io::Printer* printer) const { void MessageFieldGenerator:: GenerateGetterDeclaration(io::Printer* printer) const { printer->Print(variables_, - "const $type$& $name$() const$deprecation$;\n"); + "$deprecated_attr$const $type$& $name$() const;\n"); } void MessageFieldGenerator:: @@ -105,9 +106,9 @@ GenerateDependentAccessorDeclarations(io::Printer* printer) const { } // Arena manipulation code is out-of-line in the derived message class. printer->Print(variables_, - "$type$* mutable_$name$()$deprecation$;\n" - "$type$* $release_name$()$deprecation$;\n" - "void set_allocated_$name$($type$* $name$)$deprecation$;\n"); + "$deprecated_attr$$type$* mutable_$name$();\n" + "$deprecated_attr$$type$* $release_name$();\n" + "$deprecated_attr$void set_allocated_$name$($type$* $name$);\n"); } void MessageFieldGenerator:: @@ -115,28 +116,28 @@ GenerateAccessorDeclarations(io::Printer* printer) const { if (SupportsArenas(descriptor_)) { printer->Print(variables_, "private:\n" - "void _slow_mutable_$name$()$deprecation$;\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$)$deprecation$;\n"); + " ::google::protobuf::Arena* message_arena, $type$** $name$);\n"); } printer->Print(variables_, - "$type$* _slow_$release_name$()$deprecation$;\n" + "$type$* _slow_$release_name$();\n" "public:\n"); } GenerateGetterDeclaration(printer); if (!dependent_field_) { printer->Print(variables_, - "$type$* mutable_$name$()$deprecation$;\n" - "$type$* $release_name$()$deprecation$;\n" - "void set_allocated_$name$($type$* $name$)$deprecation$;\n"); + "$deprecated_attr$$type$* mutable_$name$();\n" + "$deprecated_attr$$type$* $release_name$();\n" + "$deprecated_attr$void set_allocated_$name$($type$* $name$);\n"); } if (SupportsArenas(descriptor_)) { printer->Print(variables_, - "$type$* unsafe_arena_release_$name$()$deprecation$;\n" - "void unsafe_arena_set_allocated_$name$(\n" - " $type$* $name$)$deprecation$;\n"); + "$deprecated_attr$$type$* unsafe_arena_release_$name$();\n" + "$deprecated_attr$void unsafe_arena_set_allocated_$name$(\n" + " $type$* $name$);\n"); } } @@ -167,6 +168,7 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions( " }\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" @@ -246,6 +248,7 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { "}\n" "template <class T>\n" "inline $type$* $dependent_classname$::$release_name$() {\n" + " // @@protoc_insertion_point(field_release:$full_name$)\n" " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" " $clear_hasbit$\n" " if ($this_message$GetArenaNoVirtual() != NULL) {\n" @@ -305,6 +308,7 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { "}\n" "template <class T>\n" "inline $type$* $dependent_classname$::$release_name$() {\n" + " // @@protoc_insertion_point(field_release:$full_name$)\n" " $clear_hasbit$\n" " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" " $dependent_typename$* temp = $name$_;\n" @@ -349,11 +353,11 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, " // @@protoc_insertion_point(field_get:$full_name$)\n"); PrintHandlingOptionalStaticInitializers( - variables, descriptor_->file(), printer, - // With static initializers. - " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n", - // Without. - " return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n"); + variables, descriptor_->file(), options_, printer, + // With static initializers. + " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n", + // Without. + " return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n"); printer->Print(variables, "}\n"); if (dependent_field_) { @@ -373,6 +377,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, "}\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" @@ -426,6 +431,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, "}\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" @@ -547,7 +553,7 @@ GenerateDependentAccessorDeclarations(io::Printer* printer) const { return; } printer->Print(variables_, - "const $type$& $name$() const$deprecation$;\n"); + "$deprecated_attr$const $type$& $name$() const;\n"); MessageFieldGenerator::GenerateDependentAccessorDeclarations(printer); } @@ -560,7 +566,7 @@ GenerateGetterDeclaration(io::Printer* printer) const { return; } printer->Print(variables_, - "const $type$& $name$() const$deprecation$;\n"); + "$deprecated_attr$const $type$& $name$() const;\n"); } void MessageOneofFieldGenerator:: @@ -651,6 +657,7 @@ InternalGenerateInlineAccessorDefinitions(const map<string, string>& variables, "$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" " if ($this_message$GetArenaNoVirtual() != NULL) {\n" @@ -706,6 +713,8 @@ InternalGenerateInlineAccessorDefinitions(const map<string, string>& variables, " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n" "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n" + " // @@protoc_insertion_point(field_unsafe_arena_release" + ":$full_name$)\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" " $type$* temp = $oneof_prefix$$name$_;\n" @@ -744,6 +753,7 @@ InternalGenerateInlineAccessorDefinitions(const map<string, string>& variables, "$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" @@ -805,12 +815,12 @@ GenerateConstructorCode(io::Printer* printer) const { // =================================================================== -RepeatedMessageFieldGenerator:: -RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : descriptor_(descriptor), - dependent_field_(options.proto_h && IsFieldDependent(descriptor)), - dependent_getter_(dependent_field_ && options.safe_boundary_check) { +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); } @@ -825,23 +835,23 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedMessageFieldGenerator:: InternalGenerateTypeDependentAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "$type$* mutable_$name$(int index)$deprecation$;\n" - "$type$* add_$name$()$deprecation$;\n"); + "$deprecated_attr$$type$* mutable_$name$(int index);\n" + "$deprecated_attr$$type$* add_$name$();\n"); if (dependent_getter_) { printer->Print(variables_, - "const ::google::protobuf::RepeatedPtrField< $type$ >&\n" - " $name$() const$deprecation$;\n"); + "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n" + " $name$() const;\n"); } printer->Print(variables_, - "::google::protobuf::RepeatedPtrField< $type$ >*\n" - " mutable_$name$()$deprecation$;\n"); + "$deprecated_attr$::google::protobuf::RepeatedPtrField< $type$ >*\n" + " mutable_$name$();\n"); } void RepeatedMessageFieldGenerator:: GenerateDependentAccessorDeclarations(io::Printer* printer) const { if (dependent_getter_) { printer->Print(variables_, - "const $type$& $name$(int index) const$deprecation$;\n"); + "$deprecated_attr$const $type$& $name$(int index) const;\n"); } if (dependent_field_) { InternalGenerateTypeDependentAccessorDeclarations(printer); @@ -852,15 +862,15 @@ void RepeatedMessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { if (!dependent_getter_) { printer->Print(variables_, - "const $type$& $name$(int index) const$deprecation$;\n"); + "$deprecated_attr$const $type$& $name$(int index) const;\n"); } if (!dependent_field_) { InternalGenerateTypeDependentAccessorDeclarations(printer); } if (!dependent_getter_) { printer->Print(variables_, - "const ::google::protobuf::RepeatedPtrField< $type$ >&\n" - " $name$() const$deprecation$;\n"); + "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n" + " $name$() const;\n"); } } diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h index 35efd0fa..d8d9279c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h @@ -46,8 +46,8 @@ namespace cpp { class MessageFieldGenerator : public FieldGenerator { public: - explicit MessageFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + MessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~MessageFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -83,8 +83,8 @@ class MessageFieldGenerator : public FieldGenerator { class MessageOneofFieldGenerator : public MessageFieldGenerator { public: - explicit MessageOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + MessageOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~MessageOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -110,8 +110,8 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator { class RepeatedMessageFieldGenerator : public FieldGenerator { public: - explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~RepeatedMessageFieldGenerator(); // implements FieldGenerator --------------------------------------- diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h index e908362b..ab1d2ed3 100644 --- a/src/google/protobuf/compiler/cpp/cpp_options.h +++ b/src/google/protobuf/compiler/cpp/cpp_options.h @@ -44,11 +44,16 @@ namespace cpp { // Generator options (see generator.cc for a description of each): struct Options { Options() - : safe_boundary_check(false), proto_h(false), annotate_headers(false) {} + : safe_boundary_check(false), + proto_h(false), + annotate_headers(false), + enforce_lite(false) {} + string dllexport_decl; bool safe_boundary_check; bool proto_h; bool annotate_headers; + bool enforce_lite; string annotation_pragma_name; string annotation_guard_name; }; diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc index d1efbfe6..34a41d82 100644 --- a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc @@ -44,9 +44,10 @@ #include <google/protobuf/io/zero_copy_stream.h> #include <google/protobuf/io/printer.h> +#include <google/protobuf/testing/file.h> +#include <google/protobuf/testing/file.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> -#include <google/protobuf/testing/file.h> namespace google { namespace protobuf { diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc index 9f929d37..650f0381 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc @@ -100,10 +100,9 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, // =================================================================== -PrimitiveFieldGenerator:: -PrimitiveFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : descriptor_(descriptor) { +PrimitiveFieldGenerator::PrimitiveFieldGenerator( + const FieldDescriptor* descriptor, const Options& options) + : FieldGenerator(options), descriptor_(descriptor) { SetPrimitiveVariables(descriptor, &variables_, options); } @@ -117,8 +116,8 @@ GeneratePrivateMembers(io::Printer* printer) const { void PrimitiveFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "$type$ $name$() const$deprecation$;\n" - "void set_$name$($type$ value)$deprecation$;\n"); + "$deprecated_attr$$type$ $name$() const;\n" + "$deprecated_attr$void set_$name$($type$ value);\n"); } void PrimitiveFieldGenerator:: @@ -256,10 +255,9 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { // =================================================================== -RepeatedPrimitiveFieldGenerator:: -RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : descriptor_(descriptor) { +RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( + const FieldDescriptor* descriptor, const Options& options) + : FieldGenerator(options), descriptor_(descriptor) { SetPrimitiveVariables(descriptor, &variables_, options); if (descriptor->is_packed()) { @@ -277,7 +275,8 @@ void RepeatedPrimitiveFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { printer->Print(variables_, "::google::protobuf::RepeatedField< $type$ > $name$_;\n"); - if (descriptor_->is_packed() && HasGeneratedMethods(descriptor_->file())) { + if (descriptor_->is_packed() && + HasGeneratedMethods(descriptor_->file(), options_)) { printer->Print(variables_, "mutable int _$name$_cached_byte_size_;\n"); } @@ -286,14 +285,14 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedPrimitiveFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "$type$ $name$(int index) const$deprecation$;\n" - "void set_$name$(int index, $type$ value)$deprecation$;\n" - "void add_$name$($type$ value)$deprecation$;\n"); + "$deprecated_attr$$type$ $name$(int index) const;\n" + "$deprecated_attr$void set_$name$(int index, $type$ value);\n" + "$deprecated_attr$void add_$name$($type$ value);\n"); printer->Print(variables_, - "const ::google::protobuf::RepeatedField< $type$ >&\n" - " $name$() const$deprecation$;\n" - "::google::protobuf::RepeatedField< $type$ >*\n" - " mutable_$name$()$deprecation$;\n"); + "$deprecated_attr$const ::google::protobuf::RepeatedField< $type$ >&\n" + " $name$() const;\n" + "$deprecated_attr$::google::protobuf::RepeatedField< $type$ >*\n" + " mutable_$name$();\n"); } void RepeatedPrimitiveFieldGenerator:: diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h index fcd7d684..655ebde4 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h @@ -46,8 +46,8 @@ namespace cpp { class PrimitiveFieldGenerator : public FieldGenerator { public: - explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + PrimitiveFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~PrimitiveFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -74,8 +74,8 @@ class PrimitiveFieldGenerator : public FieldGenerator { class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { public: - explicit PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~PrimitiveOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -92,8 +92,8 @@ class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { class RepeatedPrimitiveFieldGenerator : public FieldGenerator { public: - explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~RepeatedPrimitiveFieldGenerator(); // implements FieldGenerator --------------------------------------- diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index 6b0821a6..1d743457 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -76,10 +76,9 @@ void SetStringVariables(const FieldDescriptor* descriptor, // =================================================================== -StringFieldGenerator:: -StringFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : descriptor_(descriptor) { +StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : FieldGenerator(options), descriptor_(descriptor) { SetStringVariables(descriptor, &variables_, options); } @@ -140,19 +139,19 @@ GenerateAccessorDeclarations(io::Printer* printer) const { } printer->Print(variables_, - "const ::std::string& $name$() const$deprecation$;\n" - "void set_$name$(const ::std::string& value)$deprecation$;\n" - "void set_$name$(const char* value)$deprecation$;\n" - "void set_$name$(const $pointer_type$* value, size_t size)" - "$deprecation$;\n" - "::std::string* mutable_$name$()$deprecation$;\n" - "::std::string* $release_name$()$deprecation$;\n" - "void set_allocated_$name$(::std::string* $name$)$deprecation$;\n"); + "$deprecated_attr$const ::std::string& $name$() const;\n" + "$deprecated_attr$void set_$name$(const ::std::string& value);\n" + "$deprecated_attr$void set_$name$(const char* value);\n" + "$deprecated_attr$void set_$name$(const $pointer_type$* value, size_t size)" + ";\n" + "$deprecated_attr$::std::string* mutable_$name$();\n" + "$deprecated_attr$::std::string* $release_name$();\n" + "$deprecated_attr$void set_allocated_$name$(::std::string* $name$);\n"); if (SupportsArenas(descriptor_)) { printer->Print(variables_, - "::std::string* unsafe_arena_release_$name$()$deprecation$;\n" - "void unsafe_arena_set_allocated_$name$(\n" - " ::std::string* $name$)$deprecation$;\n"); + "$deprecated_attr$::std::string* unsafe_arena_release_$name$();\n" + "$deprecated_attr$void unsafe_arena_set_allocated_$name$(\n" + " ::std::string* $name$);\n"); } @@ -199,10 +198,12 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, " 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" @@ -228,7 +229,8 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, " }\n" " $name$_.UnsafeArenaSetAllocated($default_variable$,\n" " $name$, GetArenaNoVirtual());\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" + " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:" + "$full_name$)\n" "}\n"); } else { // No-arena case. @@ -261,6 +263,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, " 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" @@ -369,7 +372,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - descriptor_, true, variables_, + descriptor_, options_, true, variables_, "this->$name$().data(), this->$name$().length(),\n", printer); } } @@ -378,7 +381,7 @@ void StringFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - descriptor_, false, variables_, + descriptor_, options_, false, variables_, "this->$name$().data(), this->$name$().length(),\n", printer); } printer->Print(variables_, @@ -390,7 +393,7 @@ void StringFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - descriptor_, false, variables_, + descriptor_, options_, false, variables_, "this->$name$().data(), this->$name$().length(),\n", printer); } printer->Print(variables_, @@ -477,6 +480,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, " // @@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" @@ -486,6 +490,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, " }\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" @@ -519,7 +524,8 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, " $oneof_prefix$$name$_.UnsafeArenaSetAllocated($default_variable$, " "$name$, GetArenaNoVirtual());\n" " }\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" + " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:" + "$full_name$)\n" "}\n"); } else { // No-arena case. @@ -572,6 +578,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, " 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" @@ -658,7 +665,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - descriptor_, true, variables_, + descriptor_, options_, true, variables_, "this->$name$().data(), this->$name$().length(),\n", printer); } } @@ -666,10 +673,9 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { // =================================================================== -RepeatedStringFieldGenerator:: -RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : descriptor_(descriptor) { +RepeatedStringFieldGenerator::RepeatedStringFieldGenerator( + const FieldDescriptor* descriptor, const Options& options) + : FieldGenerator(options), descriptor_(descriptor) { SetStringVariables(descriptor, &variables_, options); } @@ -696,24 +702,24 @@ GenerateAccessorDeclarations(io::Printer* printer) const { } printer->Print(variables_, - "const ::std::string& $name$(int index) const$deprecation$;\n" - "::std::string* mutable_$name$(int index)$deprecation$;\n" - "void set_$name$(int index, const ::std::string& value)$deprecation$;\n" - "void set_$name$(int index, const char* value)$deprecation$;\n" + "$deprecated_attr$const ::std::string& $name$(int index) const;\n" + "$deprecated_attr$::std::string* mutable_$name$(int index);\n" + "$deprecated_attr$void set_$name$(int index, const ::std::string& value);\n" + "$deprecated_attr$void set_$name$(int index, const char* value);\n" "" - "void set_$name$(int index, const $pointer_type$* value, size_t size)" - "$deprecation$;\n" - "::std::string* add_$name$()$deprecation$;\n" - "void add_$name$(const ::std::string& value)$deprecation$;\n" - "void add_$name$(const char* value)$deprecation$;\n" - "void add_$name$(const $pointer_type$* value, size_t size)" - "$deprecation$;\n"); + "$deprecated_attr$void set_$name$(" + "int index, const $pointer_type$* value, size_t size);\n" + "$deprecated_attr$::std::string* add_$name$();\n" + "$deprecated_attr$void add_$name$(const ::std::string& value);\n" + "$deprecated_attr$void add_$name$(const char* value);\n" + "$deprecated_attr$void add_$name$(const $pointer_type$* value, size_t size)" + ";\n"); printer->Print(variables_, - "const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const" - "$deprecation$;\n" - "::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()" - "$deprecation$;\n"); + "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() " + "const;\n" + "$deprecated_attr$::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()" + ";\n"); if (unknown_ctype) { printer->Outdent(); @@ -752,6 +758,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, " // @@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" @@ -807,7 +814,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { " input, this->add_$name$()));\n"); if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - descriptor_, true, variables_, + descriptor_, options_, true, variables_, "this->$name$(this->$name$_size() - 1).data(),\n" "this->$name$(this->$name$_size() - 1).length(),\n", printer); @@ -821,7 +828,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { printer->Indent(); if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - descriptor_, false, variables_, + descriptor_, options_, false, variables_, "this->$name$(i).data(), this->$name$(i).length(),\n", printer); } printer->Outdent(); @@ -838,7 +845,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { printer->Indent(); if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - descriptor_, false, variables_, + descriptor_, options_, false, variables_, "this->$name$(i).data(), this->$name$(i).length(),\n", printer); } printer->Outdent(); diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h index 616e2067..cb4e8772 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h @@ -46,8 +46,8 @@ namespace cpp { class StringFieldGenerator : public FieldGenerator { public: - explicit StringFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + StringFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~StringFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -79,8 +79,8 @@ class StringFieldGenerator : public FieldGenerator { class StringOneofFieldGenerator : public StringFieldGenerator { public: - explicit StringOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + StringOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~StringOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -99,8 +99,8 @@ class StringOneofFieldGenerator : public StringFieldGenerator { class RepeatedStringFieldGenerator : public FieldGenerator { public: - explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~RepeatedStringFieldGenerator(); // implements FieldGenerator --------------------------------------- diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index 148da883..5d82946d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -1252,7 +1252,7 @@ class GeneratedServiceTest : public testing::Test { foo_(descriptor_->FindMethodByName("Foo")), bar_(descriptor_->FindMethodByName("Bar")), stub_(&mock_channel_), - done_(google::protobuf::internal::NewPermanentCallback(&DoNothing)) {} + done_(::google::protobuf::internal::NewPermanentCallback(&DoNothing)) {} virtual void SetUp() { ASSERT_TRUE(foo_ != NULL); diff --git a/src/google/protobuf/compiler/cpp/metadata_test.cc b/src/google/protobuf/compiler/cpp/metadata_test.cc index 61dc283a..edd30780 100644 --- a/src/google/protobuf/compiler/cpp/metadata_test.cc +++ b/src/google/protobuf/compiler/cpp/metadata_test.cc @@ -41,9 +41,10 @@ #include <google/protobuf/io/printer.h> #include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/testing/file.h> +#include <google/protobuf/testing/file.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> -#include <google/protobuf/testing/file.h> namespace google { namespace protobuf { diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc index 9616f172..bdfcc2be 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc @@ -41,6 +41,7 @@ #include <google/protobuf/compiler/csharp/csharp_doc_comment.h> #include <google/protobuf/compiler/csharp/csharp_enum.h> #include <google/protobuf/compiler/csharp/csharp_helpers.h> +#include <google/protobuf/compiler/csharp/csharp_options.h> using google::protobuf::internal::scoped_ptr; @@ -64,11 +65,24 @@ void EnumGenerator::Generate(io::Printer* printer) { "access_level", class_access_level(), "name", descriptor_->name()); printer->Indent(); + std::set<string> used_names; for (int i = 0; i < descriptor_->value_count(); i++) { WriteEnumValueDocComment(printer, descriptor_->value(i)); - printer->Print("$name$ = $number$,\n", - "name", descriptor_->value(i)->name(), - "number", SimpleItoa(descriptor_->value(i)->number())); + string original_name = descriptor_->value(i)->name(); + string name = options()->legacy_enum_values + ? descriptor_->value(i)->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. + GOOGLE_LOG(WARNING) << "Duplicate enum value " << name << " (originally " << original_name + << ") in " << descriptor_->name() << "; adding underscore to distinguish"; + name += "_"; + } + printer->Print("[pbr::OriginalName(\"$original_name$\")] $name$ = $number$,\n", + "original_name", original_name, + "name", name, + "number", SimpleItoa(descriptor_->value(i)->number())); } printer->Outdent(); printer->Print("}\n"); diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index 3b88954c..e3c34040 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -306,7 +306,9 @@ std::string FieldGeneratorBase::default_value() { std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) { switch (descriptor->type()) { case FieldDescriptor::TYPE_ENUM: - return type_name() + "." + descriptor->default_value_enum()->name(); + // 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"; case FieldDescriptor::TYPE_MESSAGE: case FieldDescriptor::TYPE_GROUP: if (IsWrapperType(descriptor)) { diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc index c13ed65b..d74e8c88 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator.cc +++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc @@ -83,6 +83,9 @@ 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 == "legacy_enum_values") { + // TODO: Remove this before final release + cli_options.legacy_enum_values = true; } else { *error = "Unknown generator option: " + options[i].first; return false; diff --git a/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc index 7ef7df42..5755fee0 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc +++ b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc @@ -30,8 +30,8 @@ #include <memory> -#include <google/protobuf/compiler/ruby/ruby_generator.h> #include <google/protobuf/compiler/command_line_interface.h> +#include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/io/zero_copy_stream.h> #include <google/protobuf/io/printer.h> @@ -45,7 +45,23 @@ namespace compiler { namespace csharp { namespace { -// TODO(jtattermusch): add some tests. +TEST(CSharpEnumValue, PascalCasedPrefixStripping) { + EXPECT_EQ("Bar", GetEnumValueName("Foo", "BAR")); + EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "BAR_BAZ")); + EXPECT_EQ("Bar", GetEnumValueName("Foo", "FOO_BAR")); + EXPECT_EQ("Bar", GetEnumValueName("Foo", "FOO__BAR")); + EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "FOO_BAR_BAZ")); + EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "Foo_BarBaz")); + EXPECT_EQ("Bar", GetEnumValueName("FO_O", "FOO_BAR")); + EXPECT_EQ("Bar", GetEnumValueName("FOO", "F_O_O_BAR")); + EXPECT_EQ("Bar", GetEnumValueName("Foo", "BAR")); + EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "BAR_BAZ")); + EXPECT_EQ("Foo", GetEnumValueName("Foo", "FOO")); + EXPECT_EQ("Foo", GetEnumValueName("Foo", "FOO___")); + // Identifiers can't start with digits + EXPECT_EQ("_2Bar", GetEnumValueName("Foo", "FOO_2_BAR")); + EXPECT_EQ("_2", GetEnumValueName("Foo", "FOO___2")); +} } // namespace } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index 41265f9a..6c154c5a 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -178,6 +178,104 @@ std::string UnderscoresToPascalCase(const std::string& input) { return UnderscoresToCamelCase(input, true); } +// Convert a string which is expected to be SHOUTY_CASE (but may not be *precisely* shouty) +// into a PascalCase string. Precise rules implemented: + +// Previous input character Current character Case +// Any Non-alphanumeric Skipped +// None - first char of input Alphanumeric Upper +// Non-letter (e.g. _ or 1) Alphanumeric Upper +// Numeric Alphanumeric Upper +// Lower letter Alphanumeric Same as current +// Upper letter Alphanumeric Lower +std::string ShoutyToPascalCase(const std::string& input) { + 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; + } + if (!ascii_isalnum(previous)) { + result += ascii_toupper(current); + } else if (ascii_isdigit(previous)) { + result += ascii_toupper(current); + } else if (ascii_islower(previous)) { + result += current; + } else { + result += ascii_tolower(current); + } + previous = current; + } + return result; +} + +// Attempt to remove a prefix from a value, ignoring casing and skipping underscores. +// (foo, foo_bar) => bar - underscore after prefix is skipped +// (FOO, foo_bar) => bar - casing is ignored +// (foo_bar, foobarbaz) => baz - underscore in prefix is ignored +// (foobar, foo_barbaz) => baz - underscore in value is ignored +// (foo, bar) => bar - prefix isn't matched; return original value +std::string TryRemovePrefix(const std::string& prefix, const std::string& value) { + // First normalize to a lower-case no-underscores prefix to match against + std::string prefix_to_match = ""; + for (size_t i = 0; i < prefix.size(); i++) { + if (prefix[i] != '_') { + 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; + prefix_index < prefix_to_match.size() && value_index < value.size(); + value_index++) { + // Skip over underscores in the value + if (value[value_index] == '_') { + continue; + } + if (ascii_tolower(value[value_index]) != prefix_to_match[prefix_index++]) { + // Failed to match the prefix - bail out early. + return value; + } + } + + // If we didn't finish looking through the prefix, we can't strip it. + if (prefix_index < prefix_to_match.size()) { + return value; + } + + // Step over any underscores after the prefix + while (value_index < value.size() && value[value_index] == '_') { + value_index++; + } + + // If there's nothing left (e.g. it was a prefix with only underscores afterwards), don't strip. + if (value_index == value.size()) { + return value; + } + + return value.substr(value_index); +} + +// Format the enum value name in a pleasant way for C#: +// - Strip the enum name as a prefix if possible +// - Convert to PascalCase. +// For example, an enum called Color with a value of COLOR_BLUE should +// result in an enum value in C# called just Blue +std::string GetEnumValueName(const std::string& enum_name, const std::string& enum_value_name) { + std::string stripped = TryRemovePrefix(enum_name, enum_value_name); + std::string result = ShoutyToPascalCase(stripped); + // Just in case we have an enum name of FOO and a value of FOO_2... make sure the returned + // string is a valid identifier. + if (ascii_isdigit(result[0])) { + result = "_" + result; + } + return result; +} + std::string ToCSharpName(const std::string& name, const FileDescriptor* file) { std::string result = GetFileNamespace(file); if (result != "") { diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h index eaf85014..1563ca7e 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.h +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h @@ -36,6 +36,7 @@ #define GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__ #include <string> +#include <google/protobuf/stubs/port.h> #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/descriptor.h> #include <google/protobuf/compiler/code_generator.h> @@ -93,6 +94,10 @@ inline std::string UnderscoresToCamelCase(const std::string& input, bool cap_nex 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); + // TODO(jtattermusch): perhaps we could move this to strutil std::string StringToBase64(const std::string& input); diff --git a/src/google/protobuf/compiler/csharp/csharp_options.h b/src/google/protobuf/compiler/csharp/csharp_options.h index 426fb3b5..4079bf7f 100644 --- a/src/google/protobuf/compiler/csharp/csharp_options.h +++ b/src/google/protobuf/compiler/csharp/csharp_options.h @@ -45,7 +45,8 @@ struct Options { file_extension(".cs"), base_namespace(""), base_namespace_specified(false), - internal_access(false) { + internal_access(false), + legacy_enum_values(false) { } // Extension of the generated file. Defaults to ".cs" string file_extension; @@ -68,6 +69,12 @@ struct Options { // Whether the generated classes should have accessibility level of "internal". // Defaults to false that generates "public" classes. bool internal_access; + // By default, C# codegen now uses PascalCased enum values names, after + // removing the enum type name as a prefix (if it *is* a prefix of the value). + // Setting this option reverts to the previous behavior of just copying the + // value name specified in the .proto file, allowing gradual migration. + // This option will be removed before final release. + bool legacy_enum_values; }; } // namespace csharp diff --git a/src/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc index be19aa2e..1b6e9700 100644 --- a/src/google/protobuf/compiler/importer_unittest.cc +++ b/src/google/protobuf/compiler/importer_unittest.cc @@ -32,25 +32,26 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include <google/protobuf/compiler/importer.h> + #include <google/protobuf/stubs/hash.h> #include <memory> #ifndef _SHARED_PTR_H #include <google/protobuf/stubs/shared_ptr.h> #endif -#include <google/protobuf/compiler/importer.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/testing/file.h> -#include <google/protobuf/io/zero_copy_stream_impl.h> - -#include <google/protobuf/stubs/map_util.h> #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/testing/file.h> +#include <google/protobuf/testing/file.h> +#include <google/protobuf/testing/file.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/descriptor.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/substitute.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> +#include <google/protobuf/stubs/map_util.h> namespace google { namespace protobuf { diff --git a/src/google/protobuf/compiler/java/java_doc_comment.cc b/src/google/protobuf/compiler/java/java_doc_comment.cc index 663f0c97..0b5caba4 100644 --- a/src/google/protobuf/compiler/java/java_doc_comment.cc +++ b/src/google/protobuf/compiler/java/java_doc_comment.cc @@ -120,9 +120,7 @@ static void WriteDocCommentBodyForLocation( lines.pop_back(); } - printer->Print( - " *\n" - " * <pre>\n"); + printer->Print(" * <pre>\n"); for (int i = 0; i < lines.size(); i++) { // Most lines should start with a space. Watch out for lines that start // with a /, since putting that right after the leading asterisk will @@ -133,7 +131,9 @@ static void WriteDocCommentBodyForLocation( printer->Print(" *$line$\n", "line", lines[i]); } } - printer->Print(" * </pre>\n"); + printer->Print( + " * </pre>\n" + " *\n"); } } @@ -163,12 +163,12 @@ static string FirstLineOf(const string& value) { } void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) { + printer->Print("/**\n"); + WriteDocCommentBody(printer, message); printer->Print( - "/**\n" - " * Protobuf type {@code $fullname$}\n", + " * Protobuf type {@code $fullname$}\n" + " */\n", "fullname", EscapeJavadoc(message->full_name())); - WriteDocCommentBody(printer, message); - printer->Print(" */\n"); } void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) { @@ -176,55 +176,55 @@ void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) { // etc., but in practice everyone already knows the difference between these // so it's redundant information. - // We use the field declaration as the first line of the comment, e.g.: + // 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; - // This communicates a lot of information about the field in a small space. // If the field is a group, the debug string might end with {. + printer->Print("/**\n"); + WriteDocCommentBody(printer, field); printer->Print( - "/**\n" " * <code>$def$</code>\n", "def", EscapeJavadoc(FirstLineOf(field->DebugString()))); - WriteDocCommentBody(printer, field); printer->Print(" */\n"); } void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) { + printer->Print("/**\n"); + WriteDocCommentBody(printer, enum_); printer->Print( - "/**\n" - " * Protobuf enum {@code $fullname$}\n", + " * Protobuf enum {@code $fullname$}\n" + " */\n", "fullname", EscapeJavadoc(enum_->full_name())); - WriteDocCommentBody(printer, enum_); - printer->Print(" */\n"); } void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value) { + printer->Print("/**\n"); + WriteDocCommentBody(printer, value); printer->Print( - "/**\n" - " * <code>$def$</code>\n", + " * <code>$def$</code>\n" + " */\n", "def", EscapeJavadoc(FirstLineOf(value->DebugString()))); - WriteDocCommentBody(printer, value); - printer->Print(" */\n"); } void WriteServiceDocComment(io::Printer* printer, const ServiceDescriptor* service) { + printer->Print("/**\n"); + WriteDocCommentBody(printer, service); printer->Print( - "/**\n" - " * Protobuf service {@code $fullname$}\n", + " * Protobuf service {@code $fullname$}\n" + " */\n", "fullname", EscapeJavadoc(service->full_name())); - WriteDocCommentBody(printer, service); - printer->Print(" */\n"); } void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method) { + printer->Print("/**\n"); + WriteDocCommentBody(printer, method); printer->Print( - "/**\n" - " * <code>$def$</code>\n", + " * <code>$def$</code>\n" + " */\n", "def", EscapeJavadoc(FirstLineOf(method->DebugString()))); - WriteDocCommentBody(printer, method); - printer->Print(" */\n"); } } // namespace java diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc index 9eea873a..947b80e4 100644 --- a/src/google/protobuf/compiler/java/java_enum.cc +++ b/src/google/protobuf/compiler/java/java_enum.cc @@ -92,6 +92,16 @@ void EnumGenerator::Generate(io::Printer* printer) { "classname", descriptor_->name()); printer->Indent(); + bool ordinal_is_index = true; + string index_text = "ordinal()"; + for (int i = 0; i < canonical_values_.size(); i++) { + if (canonical_values_[i]->index() != i) { + ordinal_is_index = false; + index_text = "index"; + break; + } + } + for (int i = 0; i < canonical_values_.size(); i++) { map<string, string> vars; vars["name"] = canonical_values_[i]->name(); @@ -101,12 +111,21 @@ void EnumGenerator::Generate(io::Printer* printer) { if (canonical_values_[i]->options().deprecated()) { printer->Print("@java.lang.Deprecated\n"); } - printer->Print(vars, - "$name$($index$, $number$),\n"); + if (ordinal_is_index) { + printer->Print(vars, + "$name$($number$),\n"); + } else { + printer->Print(vars, + "$name$($index$, $number$),\n"); + } } if (SupportUnknownEnumValue(descriptor_->file())) { - printer->Print("UNRECOGNIZED(-1, -1),\n"); + if (ordinal_is_index) { + printer->Print("UNRECOGNIZED(-1),\n"); + } else { + printer->Print("UNRECOGNIZED(-1, -1),\n"); + } } printer->Print( @@ -141,11 +160,19 @@ void EnumGenerator::Generate(io::Printer* printer) { "\n" "public final int getNumber() {\n"); if (SupportUnknownEnumValue(descriptor_->file())) { - 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 (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"); + } 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"); + } } printer->Print( " return value;\n" @@ -200,14 +227,15 @@ void EnumGenerator::Generate(io::Printer* printer) { printer->Print( "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n" " getValueDescriptor() {\n" - " return getDescriptor().getValues().get(index);\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"); + " 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 @@ -313,16 +341,27 @@ void EnumGenerator::Generate(io::Printer* printer) { "}\n" "\n"); - printer->Print("private final int index;\n"); + if (!ordinal_is_index) { + printer->Print("private final int index;\n"); + } } // ----------------------------------------------------------------- printer->Print( - "private final int value;\n\n" - "private $classname$(int index, int value) {\n", - "classname", descriptor_->name()); - if (HasDescriptorMethods(descriptor_, context_->EnforceLite())) { + "private final int value;\n\n"); + + if (ordinal_is_index) { + printer->Print( + "private $classname$(int value) {\n", + "classname", descriptor_->name()); + } else { + 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( 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 5b98637b..908d6db4 100644 --- a/src/google/protobuf/compiler/java/java_enum_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc @@ -262,17 +262,15 @@ GenerateInitializationCode(io::Printer* printer) const { } void ImmutableEnumFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); + "$name$_ = visitor.visitInt(has$capitalized_name$(), $name$_,\n" + " other.has$capitalized_name$(), other.$name$_);\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"); + "$name$_ = visitor.visitInt($name$_ != $default_number$, $name$_," + " other.$name$_ != $default_number$, other.$name$_);\n"); } else { GOOGLE_LOG(FATAL) << "Can't reach here."; } @@ -466,14 +464,10 @@ GenerateBuilderMembers(io::Printer* printer) const { } void ImmutableEnumOneofFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { - if (SupportUnknownEnumValue(descriptor_->file())) { - 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"); - } +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:: @@ -645,7 +639,8 @@ GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private void ensure$capitalized_name$IsMutable() {\n" " if (!$is_mutable$) {\n" - " $name$_ = newIntList($name$_);\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" " }\n" "}\n"); WriteFieldDocComment(printer, descriptor_); @@ -805,21 +800,9 @@ GenerateInitializationCode(io::Printer* printer) const { } void RepeatedImmutableEnumFieldLiteGenerator:: -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" - " } else {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addAll(other.$name$_);\n" - " }\n" - "}\n"); +GenerateVisitCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_= visitor.visitIntList($name$_, other.$name$_);\n"); } void RepeatedImmutableEnumFieldLiteGenerator:: @@ -831,27 +814,23 @@ GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { 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_, - "int rawValue = input.readEnum();\n" - "if (!$is_mutable$) {\n" - " $name$_ = newIntList();\n" - "}\n" - "$name$_.addInt(rawValue);\n"); + "$name$_.addInt(input.readEnum());\n"); } else { printer->Print(variables_, "int rawValue = input.readEnum();\n" "$type$ value = $type$.forNumber(rawValue);\n" - "if (value == null) {\n"); - if (PreserveUnknownFields(descriptor_->containing_type())) { - printer->Print(variables_, - " super.mergeVarintField($number$, rawValue);\n"); - } - printer->Print(variables_, + "if (value == null) {\n" + // We store the unknown value in unknown fields. + " super.mergeVarintField($number$, rawValue);\n" "} else {\n" - " if (!$is_mutable$) {\n" - " $name$_ = newIntList();\n" - " }\n" " $name$_.addInt(rawValue);\n" "}\n"); } @@ -859,7 +838,11 @@ GenerateParsingCode(io::Printer* printer) const { void RepeatedImmutableEnumFieldLiteGenerator:: GenerateParsingCodeFromPacked(io::Printer* printer) const { - // Wrap GenerateParsingCode's contents with a while loop. + 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" @@ -867,7 +850,21 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const { "while(input.getBytesUntilLimit() > 0) {\n"); printer->Indent(); - GenerateParsingCode(printer); + // 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_, 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 2c41c3e4..9201b8d6 100644 --- a/src/google/protobuf/compiler/java/java_enum_field_lite.h +++ b/src/google/protobuf/compiler/java/java_enum_field_lite.h @@ -67,7 +67,7 @@ class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator { void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateMergingCode(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; @@ -101,7 +101,7 @@ class ImmutableEnumOneofFieldLiteGenerator void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateMergingCode(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; @@ -127,7 +127,7 @@ class RepeatedImmutableEnumFieldLiteGenerator void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateMergingCode(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; diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h index 0e24da24..4dd4f57f 100644 --- a/src/google/protobuf/compiler/java/java_field.h +++ b/src/google/protobuf/compiler/java/java_field.h @@ -105,7 +105,7 @@ class ImmutableFieldLiteGenerator { 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 GenerateMergingCode(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; 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 index a648f1c2..62f39302 100644 --- a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc @@ -182,12 +182,11 @@ GenerateInitializationCode(io::Printer* printer) const { } void ImmutableLazyMessageFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " $name$_.merge(other.$name$_);\n" - " $set_has_field_bit_message$;\n" - "}\n"); + "$name$_ = visitor.visitLazyMessage(\n" + " has$capitalized_name$(), $name$_,\n" + " other.has$capitalized_name$(), other.$name$_);\n"); } void ImmutableLazyMessageFieldLiteGenerator:: @@ -362,14 +361,12 @@ GenerateBuilderMembers(io::Printer* printer) const { } void ImmutableLazyMessageOneofFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(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"); + "$oneof_name$_ = visitor.visitOneofLazyMessage(\n" + " $has_oneof_case_message$,\n" + " ($lazy_type$) $oneof_name$_,\n" + " ($lazy_type$) other.$oneof_name$_);\n"); } void ImmutableLazyMessageOneofFieldLiteGenerator:: @@ -463,7 +460,8 @@ GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private void ensure$capitalized_name$IsMutable() {\n" " if (!$is_mutable$) {\n" - " $name$_ = newProtobufList($name$_);\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" " }\n" "}\n" "\n"); @@ -678,7 +676,8 @@ void RepeatedImmutableLazyMessageFieldLiteGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, "if (!$is_mutable$) {\n" - " $name$_ = newProtobufList();\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" "}\n" "$name$_.add(new com.google.protobuf.LazyFieldLite(\n" " extensionRegistry, input.readBytes()));\n"); 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 index e85ec0f3..47ebeb49 100644 --- a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h +++ b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h @@ -63,7 +63,7 @@ class ImmutableLazyMessageFieldLiteGenerator void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateMergingCode(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; @@ -82,7 +82,7 @@ class ImmutableLazyMessageOneofFieldLiteGenerator void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateMergingCode(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; diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc index 17c3646f..2a551ca4 100644 --- a/src/google/protobuf/compiler/java/java_map_field.cc +++ b/src/google/protobuf/compiler/java/java_map_field.cc @@ -215,7 +215,7 @@ GenerateMembers(io::Printer* printer) const { " if ($name$_ == null) {\n" " return com.google.protobuf.MapField$lite$.emptyMapField(\n" " $map_field_parameter$);\n" - " }\n" + " }\n" " return $name$_;\n" "}\n"); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { @@ -270,7 +270,7 @@ GenerateBuilderMembers(io::Printer* printer) const { " if ($name$_ == null) {\n" " return com.google.protobuf.MapField$lite$.emptyMapField(\n" " $map_field_parameter$);\n" - " }\n" + " }\n" " return $name$_;\n" "}\n" "private com.google.protobuf.MapField$lite$<$type_parameters$>\n" 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 6bdebb0d..b80d4139 100644 --- a/src/google/protobuf/compiler/java/java_map_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc @@ -374,10 +374,10 @@ GenerateInitializationCode(io::Printer* printer) const { } void ImmutableMapFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { printer->Print( variables_, - "internalGetMutable$capitalized_name$().mergeFrom(\n" + "$name$_ = visitor.visitMap(internalGetMutable$capitalized_name$(),\n" " other.internalGet$capitalized_name$());\n"); } 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 a09cd536..555b5c5b 100644 --- a/src/google/protobuf/compiler/java/java_map_field_lite.h +++ b/src/google/protobuf/compiler/java/java_map_field_lite.h @@ -52,7 +52,7 @@ class ImmutableMapFieldLiteGenerator : public ImmutableFieldLiteGenerator { void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateMergingCode(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; diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index dfd8ad08..4c474a48 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -89,7 +89,6 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor) MessageGenerator::~MessageGenerator() {} // =================================================================== -// TODO(api): Move this class to a separate immutable_message.cc file. ImmutableMessageGenerator::ImmutableMessageGenerator( const Descriptor* descriptor, Context* context) : MessageGenerator(descriptor), context_(context), @@ -1226,7 +1225,8 @@ GenerateParsingConstructor(io::Printer* printer) { "default: {\n" " if (!input.skipField(tag)) {\n" " done = true;\n" // it's an endgroup tag - " }\n" + " }\n"); + printer->Print( " break;\n" "}\n"); } 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 049679df..14281816 100644 --- a/src/google/protobuf/compiler/java/java_message_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc @@ -286,11 +286,9 @@ void ImmutableMessageFieldLiteGenerator:: GenerateInitializationCode(io::Printer* printer) const {} void ImmutableMessageFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " merge$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); + "$name$_ = visitor.visitMessage($name$_, other.$name$_);\n"); } void ImmutableMessageFieldLiteGenerator:: @@ -300,11 +298,18 @@ GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { void ImmutableMessageFieldLiteGenerator:: GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "$type$.Builder subBuilder = null;\n" - "if ($is_field_present_message$) {\n" - " subBuilder = $name$_.toBuilder();\n" - "}\n"); + // 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_, @@ -504,9 +509,12 @@ GenerateBuilderMembers(io::Printer* printer) const { } void ImmutableMessageOneofFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { printer->Print(variables_, - "merge$capitalized_name$(other.get$capitalized_name$());\n"); + "$oneof_name$_ = visitor.visitOneofMessage(\n" + " $has_oneof_case_message$,\n" + " $oneof_name$_,\n" + " other.$oneof_name$_);\n"); } void ImmutableMessageOneofFieldLiteGenerator:: @@ -633,7 +641,8 @@ GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private void ensure$capitalized_name$IsMutable() {\n" " if (!$is_mutable$) {\n" - " $name$_ = newProtobufList($name$_);\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" " }\n" "}\n" "\n"); @@ -851,21 +860,9 @@ GenerateInitializationCode(io::Printer* printer) const { } void RepeatedImmutableMessageFieldLiteGenerator:: -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. - printer->Print(variables_, - "if (!other.$name$_.isEmpty()) {\n" - " if ($name$_.isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - " } else {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addAll(other.$name$_);\n" - " }\n" - "}\n"); +GenerateVisitCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_= visitor.visitList($name$_, other.$name$_);\n"); } void RepeatedImmutableMessageFieldLiteGenerator:: @@ -878,7 +875,8 @@ void RepeatedImmutableMessageFieldLiteGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, "if (!$is_mutable$) {\n" - " $name$_ = newProtobufList();\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" "}\n"); if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { 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 ae26c06a..61321547 100644 --- a/src/google/protobuf/compiler/java/java_message_field_lite.h +++ b/src/google/protobuf/compiler/java/java_message_field_lite.h @@ -67,7 +67,7 @@ class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator { void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateMergingCode(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; @@ -101,7 +101,7 @@ class ImmutableMessageOneofFieldLiteGenerator void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateMergingCode(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; @@ -125,7 +125,7 @@ class RepeatedImmutableMessageFieldLiteGenerator void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateMergingCode(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; diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc index 14cc908b..d4d2593a 100644 --- a/src/google/protobuf/compiler/java/java_message_lite.cc +++ b/src/google/protobuf/compiler/java/java_message_lite.cc @@ -199,7 +199,7 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { printer->Indent(); - GenerateParsingConstructor(printer); + GenerateConstructor(printer); // Nested types for (int i = 0; i < descriptor_->enum_type_count(); i++) { @@ -322,10 +322,6 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { GenerateMessageSerializationMethods(printer); - if (HasEqualsAndHashCode(descriptor_)) { - GenerateEqualsAndHashCode(printer); - } - GenerateParseFromMethods(printer); GenerateBuilder(printer); @@ -342,16 +338,8 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { " com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n" " Object arg0, Object arg1) {\n" " switch (method) {\n" - " case PARSE_PARTIAL_FROM: {\n" - " return new $classname$(" - " (com.google.protobuf.CodedInputStream) arg0,\n" - " (com.google.protobuf.ExtensionRegistryLite) arg1);\n" - " }\n" - " case NEW_INSTANCE: {\n" - " return new $classname$(\n" - " com.google.protobuf.Internal.EMPTY_CODED_INPUT_STREAM,\n" - " com.google.protobuf.ExtensionRegistryLite\n" - " .getEmptyRegistry());\n" + " case NEW_MUTABLE_INSTANCE: {\n" + " return new $classname$();\n" " }\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); @@ -382,10 +370,18 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { printer->Print( "}\n" - "case MERGE_FROM: {\n"); + "case VISIT: {\n"); printer->Indent(); - GenerateDynamicMethodMergeFrom(printer); + GenerateDynamicMethodVisit(printer); + printer->Outdent(); + + printer->Print( + "}\n" + "case MERGE_FROM_STREAM: {\n"); + + printer->Indent(); + GenerateDynamicMethodMergeFromStream(printer); printer->Outdent(); printer->Print( @@ -433,11 +429,8 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { printer->Print( "static {\n" - " DEFAULT_INSTANCE = new $classname$(\n" - " com.google.protobuf.Internal\n" - " .EMPTY_CODED_INPUT_STREAM,\n" - " com.google.protobuf.ExtensionRegistryLite\n" - " .getEmptyRegistry());\n" + " DEFAULT_INSTANCE = new $classname$();\n" + " DEFAULT_INSTANCE.makeImmutable();\n" "}\n" "\n", "classname", descriptor_->name()); @@ -802,11 +795,13 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized( 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"); } @@ -821,19 +816,17 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuilder( // =================================================================== -void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom( +void ImmutableMessageLiteGenerator::GenerateDynamicMethodVisit( io::Printer* printer) { printer->Print( - // Optimization: If other is the default instance, we know none of its - // fields are set so we can skip the merge. - "if (arg0 == $classname$.getDefaultInstance()) return this;\n" - "$classname$ other = ($classname$) arg0;\n", + "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)).GenerateMergingCode(printer); + descriptor_->field(i)).GenerateVisitCode(printer); } } @@ -852,7 +845,7 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom( "field_name", ToUpper(field->name())); printer->Indent(); - field_generators_.get(field).GenerateMergingCode(printer); + field_generators_.get(field).GenerateVisitCode(printer); printer->Print( "break;\n"); printer->Outdent(); @@ -861,254 +854,66 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom( } 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)); - printer->Outdent(); - printer->Print( - "}\n"); - } - - // if message type has extensions - if (descriptor_->extension_range_count() > 0) { - printer->Print( - "this.mergeExtensionFields(other);\n"); - } - - if (PreserveUnknownFields(descriptor_)) { - printer->Print( - "this.mergeUnknownFields(other.unknownFields);\n"); - } - - printer->Print( - "return this;\n"); -} - -// =================================================================== - -namespace { -bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) { - if (field->is_repeated()) { - return false; - } - if (SupportFieldPresence(field->file())) { - return true; - } - return GetJavaType(field) == JAVATYPE_MESSAGE && - field->containing_oneof() == NULL; -} -} // namespace - -void ImmutableMessageLiteGenerator:: -GenerateEqualsAndHashCode(io::Printer* printer) { - printer->Print( - "@java.lang.Override\n" - "public boolean equals(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"); - // Compare non-oneofs. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (field->containing_oneof() == NULL) { - 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); - printer->Indent(); - } - field_generators_.get(field).GenerateEqualsCode(printer); - if (check_has_bits) { - printer->Outdent(); - 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); - printer->Print( - "if (!result) return false;\n" - "switch ($oneof_name$Case_) {\n", + descriptor_->oneof_decl(i))->name), "oneof_name", context_->GetOneofGeneratorInfo( 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 $field_number$:\n", - "field_number", - SimpleItoa(field->number())); - printer->Indent(); - field_generators_.get(field).GenerateEqualsCode(printer); - printer->Print("break;\n"); - printer->Outdent(); - } - printer->Print( - "case 0:\n" - "default:\n"); printer->Outdent(); - printer->Print("}\n"); - } - - if (PreserveUnknownFields(descriptor_)) { - // Always consider unknown fields for equality. This will sometimes return - // 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"); + "}\n"); } - printer->Print( - "return result;\n"); - printer->Outdent(); - printer->Print( - "}\n" - "\n"); printer->Print( - "@java.lang.Override\n" - "public int hashCode() {\n"); - printer->Indent(); - printer->Print( - "if (memoizedHashCode != 0) {\n"); + "if (visitor == com.google.protobuf.GeneratedMessageLite.MergeFromVisitor\n" + " .INSTANCE) {\n"); printer->Indent(); - printer->Print( - "return memoizedHashCode;\n"); - printer->Outdent(); - printer->Print( - "}\n" - "int hash = 41;\n"); - - // Include the hash of the class so that two objects with different types - // but the same field values will probably have different hashes. - printer->Print("hash = (19 * hash) + $classname$.class.hashCode();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + 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); + } - // hashCode non-oneofs. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (field->containing_oneof() == NULL) { - 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->Indent(); - } - field_generators_.get(field).GenerateHashCode(printer); - if (check_has_bits) { - printer->Outdent(); - printer->Print("}\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)) + .GetNumBitsForMessage(); } - } + int totalInts = (totalBits + 31) / 32; - // 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); - 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 i = 0; i < totalInts; i++) { printer->Print( - "case $field_number$:\n", - "field_number", - SimpleItoa(field->number())); - printer->Indent(); - field_generators_.get(field).GenerateHashCode(printer); - printer->Print("break;\n"); - printer->Outdent(); + "$bit_field_name$ |= other.$bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); } - printer->Print( - "case 0:\n" - "default:\n"); - printer->Outdent(); - printer->Print("}\n"); } - - printer->Print( - "hash = (29 * hash) + unknownFields.hashCode();\n"); - printer->Print( - "memoizedHashCode = hash;\n" - "return hash;\n"); printer->Outdent(); printer->Print( - "}\n" - "\n"); -} + "}\n"); -// =================================================================== -void ImmutableMessageLiteGenerator:: -GenerateExtensionRegistrationCode(io::Printer* printer) { - for (int i = 0; i < descriptor_->extension_count(); i++) { - ImmutableExtensionLiteGenerator(descriptor_->extension(i), context_) - .GenerateRegistrationCode(printer); - } - - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_) - .GenerateExtensionRegistrationCode(printer); - } + printer->Print( + "return this;\n"); } // =================================================================== -void ImmutableMessageLiteGenerator:: -GenerateParsingConstructor(io::Printer* printer) { - google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields( - SortFieldsByNumber(descriptor_)); - - printer->Print( - "private $classname$(\n" - " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n", - "classname", descriptor_->name()); - printer->Indent(); - - // Initialize all fields to default. - GenerateInitializers(printer); - - // Use builder bits to track mutable repeated fields. - int totalBuilderBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - const ImmutableFieldLiteGenerator& field = - field_generators_.get(descriptor_->field(i)); - totalBuilderBits += field.GetNumBitsForBuilder(); - } - 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)); - } +void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFromStream( + 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" "try {\n"); printer->Indent(); @@ -1156,6 +961,8 @@ GenerateParsingConstructor(io::Printer* printer) { "}\n"); } + google::protobuf::scoped_array<const FieldDescriptor * > 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(), @@ -1209,19 +1016,54 @@ GenerateParsingConstructor(io::Printer* printer) { "} finally {\n"); printer->Indent(); - // Make repeated field list immutable. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = sorted_fields[i]; - field_generators_.get(field).GenerateParsingDoneCode(printer); + printer->Outdent(); + printer->Print( + "}\n"); // finally +} + +// =================================================================== + +namespace { +bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) { + if (field->is_repeated()) { + return false; + } + if (SupportFieldPresence(field->file())) { + return true; } + return GetJavaType(field) == JAVATYPE_MESSAGE && + field->containing_oneof() == NULL; +} +} // namespace + +// =================================================================== +void ImmutableMessageLiteGenerator:: +GenerateExtensionRegistrationCode(io::Printer* printer) { + for (int i = 0; i < descriptor_->extension_count(); i++) { + ImmutableExtensionLiteGenerator(descriptor_->extension(i), context_) + .GenerateRegistrationCode(printer); + } + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_) + .GenerateExtensionRegistrationCode(printer); + } +} + +// =================================================================== +void ImmutableMessageLiteGenerator:: +GenerateConstructor(io::Printer* printer) { printer->Print( - "doneParsing();\n"); + "private $classname$() {\n", + "classname", descriptor_->name()); + printer->Indent(); + + // Initialize all fields to default. + GenerateInitializers(printer); - printer->Outdent(); printer->Outdent(); printer->Print( - " }\n" // finally "}\n"); } diff --git a/src/google/protobuf/compiler/java/java_message_lite.h b/src/google/protobuf/compiler/java/java_message_lite.h index c8ee99bd..292c1c56 100644 --- a/src/google/protobuf/compiler/java/java_message_lite.h +++ b/src/google/protobuf/compiler/java/java_message_lite.h @@ -70,12 +70,13 @@ class ImmutableMessageLiteGenerator : public MessageGenerator { void GenerateBuilder(io::Printer* printer); void GenerateDynamicMethodIsInitialized(io::Printer* printer); void GenerateDynamicMethodMakeImmutable(io::Printer* printer); - void GenerateDynamicMethodMergeFrom(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 GenerateParsingConstructor(io::Printer* printer); + void GenerateConstructor(io::Printer* printer); Context* context_; ClassNameResolver* name_resolver_; diff --git a/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc index fe527623..3e4910c8 100644 --- a/src/google/protobuf/compiler/java/java_plugin_unittest.cc +++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc @@ -44,9 +44,10 @@ #include <google/protobuf/io/zero_copy_stream.h> #include <google/protobuf/io/printer.h> +#include <google/protobuf/testing/file.h> +#include <google/protobuf/testing/file.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> -#include <google/protobuf/testing/file.h> namespace google { namespace protobuf { 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 d277e4f3..690dad12 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc @@ -86,9 +86,6 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, case JAVATYPE_BOOLEAN: (*variables)["field_list_type"] = "com.google.protobuf.Internal." + capitalized_type + "List"; - (*variables)["new_list"] = "new" + capitalized_type + "List"; - (*variables)["new_list_with_capacity"] = - "new" + capitalized_type + "ListWithCapacity"; (*variables)["empty_list"] = "empty" + capitalized_type + "List()"; (*variables)["make_name_unmodifiable"] = (*variables)["name"] + "_.makeImmutable()"; @@ -98,19 +95,21 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, (*variables)["name"] + "_.add" + capitalized_type; (*variables)["repeated_set"] = (*variables)["name"] + "_.set" + capitalized_type; + (*variables)["visit_type"] = capitalized_type; + (*variables)["visit_type_list"] = "visit" + capitalized_type + "List"; break; default: (*variables)["field_list_type"] = "com.google.protobuf.Internal.ProtobufList<" + (*variables)["boxed_type"] + ">"; - (*variables)["new_list"] = "newProtobufList"; - (*variables)["new_list_with_capacity"] = "newProtobufListWithCapacity"; (*variables)["empty_list"] = "emptyProtobufList()"; (*variables)["make_name_unmodifiable"] = (*variables)["name"] + "_.makeImmutable()"; (*variables)["repeated_get"] = (*variables)["name"] + "_.get"; (*variables)["repeated_add"] = (*variables)["name"] + "_.add"; (*variables)["repeated_set"] = (*variables)["name"] + "_.set"; + (*variables)["visit_type"] = "ByteString"; + (*variables)["visit_type_list"] = "visitList"; } if (IsReferenceType(GetJavaType(descriptor))) { @@ -297,17 +296,16 @@ GenerateBuilderClearCode(io::Printer* printer) const { } void ImmutablePrimitiveFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); + "$name$_ = visitor.visit$visit_type$(\n" + " has$capitalized_name$(), $name$_,\n" + " other.has$capitalized_name$(), other.$name$_);\n"); } else { printer->Print(variables_, - "if (other.get$capitalized_name$() != $default$) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); + "$name$_ = visitor.visit$visit_type$($name$_ != $default$, $name$_,\n" + " other.$name$_ != $default$, other.$name$_);\n"); } } @@ -539,9 +537,10 @@ GenerateBuildingCode(io::Printer* printer) const { } void ImmutablePrimitiveOneofFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { printer->Print(variables_, - "set$capitalized_name$(other.get$capitalized_name$());\n"); + "$oneof_name$_ = visitor.visitOneof$visit_type$(\n" + " $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n"); } void ImmutablePrimitiveOneofFieldLiteGenerator:: @@ -641,7 +640,8 @@ GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private void ensure$capitalized_name$IsMutable() {\n" " if (!$is_mutable$) {\n" - " $name$_ = $new_list$($name$_);\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" " }\n" "}\n"); @@ -742,21 +742,9 @@ GenerateBuilderClearCode(io::Printer* printer) const { } void RepeatedImmutablePrimitiveFieldLiteGenerator:: -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" - " } else {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addAll(other.$name$_);\n" - " }\n" - "}\n"); +GenerateVisitCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_= visitor.$visit_type_list$($name$_, other.$name$_);\n"); } void RepeatedImmutablePrimitiveFieldLiteGenerator:: @@ -777,7 +765,8 @@ GenerateParsingCode(io::Printer* printer) const { // TODO(dweis): Scan the input buffer to count and ensure capacity. printer->Print(variables_, "if (!$is_mutable$) {\n" - " $name$_ = $new_list$();\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" "}\n" "$repeated_add$(input.read$capitalized_type$());\n"); } @@ -794,10 +783,13 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const { // TODO(dweis): Scan the input buffer to count, then initialize // appropriately. printer->Print(variables_, - " $name$_ = $new_list$();\n"); + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"); } else { printer->Print(variables_, - " $name$_ = $new_list_with_capacity$(length/$fixed_size$);\n"); + " 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. 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 ad603c2a..6cfbbb98 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field_lite.h +++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.h @@ -69,7 +69,7 @@ class ImmutablePrimitiveFieldLiteGenerator 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 GenerateVisitCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; @@ -105,7 +105,7 @@ class ImmutablePrimitiveOneofFieldLiteGenerator void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; - void GenerateMergingCode(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; @@ -130,7 +130,7 @@ class RepeatedImmutablePrimitiveFieldLiteGenerator 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 GenerateVisitCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; 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 9012ab5e..0b92c021 100644 --- a/src/google/protobuf/compiler/java/java_string_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc @@ -299,20 +299,16 @@ GenerateInitializationCode(io::Printer* printer) const { } void ImmutableStringFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { - // 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_message$\n" - " $name$_ = other.$name$_;\n" - "}\n"); + "$name$_ = visitor.visitString(\n" + " has$capitalized_name$(), $name$_,\n" + " other.has$capitalized_name$(), other.$name$_);\n"); } else { printer->Print(variables_, - "if (!other.get$capitalized_name$().isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - "}\n"); + "$name$_ = visitor.visitString(!$name$_.isEmpty(), $name$_,\n" + " !other.$name$_.isEmpty(), other.$name$_);\n"); } } @@ -519,12 +515,10 @@ GenerateBuilderMembers(io::Printer* printer) const { } void ImmutableStringOneofFieldLiteGenerator:: -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. +GenerateVisitCode(io::Printer* printer) const { printer->Print(variables_, - "$set_oneof_case_message$;\n" - "$oneof_name$_ = other.$oneof_name$_;\n"); + "$oneof_name$_ = visitor.visitOneofString(\n" + " $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n"); } void ImmutableStringOneofFieldLiteGenerator:: @@ -645,8 +639,8 @@ GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private void ensure$capitalized_name$IsMutable() {\n" " if (!$is_mutable$) {\n" - " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList(\n" - " $name$_);\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" " }\n" "}\n"); @@ -773,21 +767,9 @@ GenerateInitializationCode(io::Printer* printer) const { } void RepeatedImmutableStringFieldLiteGenerator:: -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" - " } else {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addAll(other.$name$_);\n" - " }\n" - "}\n"); +GenerateVisitCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_= visitor.visitList($name$_, other.$name$_);\n"); } void RepeatedImmutableStringFieldLiteGenerator:: @@ -811,7 +793,8 @@ GenerateParsingCode(io::Printer* printer) const { } printer->Print(variables_, "if (!$is_mutable$) {\n" - " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList();\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" "}\n"); printer->Print(variables_, "$name$_.add(s);\n"); 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 4d9b4bd7..4148aa4d 100644 --- a/src/google/protobuf/compiler/java/java_string_field_lite.h +++ b/src/google/protobuf/compiler/java/java_string_field_lite.h @@ -68,7 +68,7 @@ class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator { void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateMergingCode(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; @@ -103,7 +103,7 @@ class ImmutableStringOneofFieldLiteGenerator private: void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateMergingCode(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; @@ -126,7 +126,7 @@ class RepeatedImmutableStringFieldLiteGenerator void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateMergingCode(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; diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc index 534a5b5b..3de61e80 100755 --- a/src/google/protobuf/compiler/js/js_generator.cc +++ b/src/google/protobuf/compiler/js/js_generator.cc @@ -1909,7 +1909,7 @@ void Generator::GenerateClassToObject(const GeneratorOptions& options, printer->Print( " if (includeInstance) {\n" - " obj.$$jspbMessageInstance = msg\n" + " obj.$$jspbMessageInstance = msg;\n" " }\n" " return obj;\n" "};\n" @@ -3032,8 +3032,7 @@ bool Generator::GenerateAll(const vector<const FileDescriptor*>& files, const google::protobuf::FileDescriptor* file = files[i]; string filename = options.output_dir + "/" + GetJSFilename(file->name()); - scoped_ptr<io::ZeroCopyOutputStream> output( - context->Open(filename)); + google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); GOOGLE_CHECK(output.get()); io::Printer printer(output.get(), '$'); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index fda51807..196b39dd 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -757,10 +757,11 @@ bool HasNonZeroDefaultValue(const FieldDescriptor* field) { return false; } - if (!field->has_default_value()) { - // No custom default set in the proto file. - return false; - } + // As much as checking field->has_default_value() seems useful, it isn't + // because of enums. proto2 syntax allows the first item in an enum (the + // default) to be non zero. So checking field->has_default_value() would + // result in missing this non zero default. See MessageWithOneBasedEnum in + // objectivec/Tests/unittest_objc.proto for a test Message to confirm this. // Some proto file set the default to the zero value, so make sure the value // isn't the zero case. diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index a2da8eee..e9d50a1d 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -240,6 +240,7 @@ CodeGeneratorRequest* CodeGeneratorRequest::New(::google::protobuf::Arena* arena } void CodeGeneratorRequest::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorRequest) if (has_parameter()) { parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -253,7 +254,7 @@ void CodeGeneratorRequest::Clear() { bool CodeGeneratorRequest::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorRequest) for (;;) { @@ -412,6 +413,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes( } int CodeGeneratorRequest::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorRequest) int total_size = 0; // optional string parameter = 2; @@ -448,18 +450,22 @@ int CodeGeneratorRequest::ByteSize() const { } void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const CodeGeneratorRequest* source = ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorRequest>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorRequest) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorRequest) MergeFrom(*source); } } void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); file_to_generate_.MergeFrom(from.file_to_generate_); proto_file_.MergeFrom(from.proto_file_); @@ -475,12 +481,14 @@ void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) { } void CodeGeneratorRequest::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorRequest) if (&from == this) return; Clear(); MergeFrom(from); } void CodeGeneratorRequest::CopyFrom(const CodeGeneratorRequest& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.CodeGeneratorRequest) if (&from == this) return; Clear(); MergeFrom(from); @@ -545,6 +553,7 @@ void CodeGeneratorRequest::clear_file_to_generate() { // @@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) { @@ -610,6 +619,7 @@ void CodeGeneratorRequest::clear_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()); } @@ -728,6 +738,7 @@ CodeGeneratorResponse_File* CodeGeneratorResponse_File::New(::google::protobuf:: } void CodeGeneratorResponse_File::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse.File) if (_has_bits_[0 / 32] & 7u) { if (has_name()) { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); @@ -747,7 +758,7 @@ void CodeGeneratorResponse_File::Clear() { bool CodeGeneratorResponse_File::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#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 (;;) { @@ -912,6 +923,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes( } int CodeGeneratorResponse_File::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse.File) int total_size = 0; if (_has_bits_[0 / 32] & 7u) { @@ -949,18 +961,22 @@ int CodeGeneratorResponse_File::ByteSize() const { } void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const CodeGeneratorResponse_File* source = ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse_File>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorResponse.File) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorResponse.File) MergeFrom(*source); } } void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_name()) { @@ -982,12 +998,14 @@ void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& fro } void CodeGeneratorResponse_File::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse.File) if (&from == this) return; Clear(); MergeFrom(from); } void CodeGeneratorResponse_File::CopyFrom(const CodeGeneratorResponse_File& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse.File) if (&from == this) return; Clear(); MergeFrom(from); @@ -1088,6 +1106,7 @@ CodeGeneratorResponse* CodeGeneratorResponse::New(::google::protobuf::Arena* are } void CodeGeneratorResponse::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse) if (has_error()) { error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -1100,7 +1119,7 @@ void CodeGeneratorResponse::Clear() { bool CodeGeneratorResponse::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse) for (;;) { @@ -1219,6 +1238,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes( } int CodeGeneratorResponse::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse) int total_size = 0; // optional string error = 1; @@ -1248,18 +1268,22 @@ int CodeGeneratorResponse::ByteSize() const { } void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const CodeGeneratorResponse* source = ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorResponse) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorResponse) MergeFrom(*source); } } void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); file_.MergeFrom(from.file_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { @@ -1274,12 +1298,14 @@ void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) { } void CodeGeneratorResponse::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse) if (&from == this) return; Clear(); MergeFrom(from); } void CodeGeneratorResponse::CopyFrom(const CodeGeneratorResponse& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse) if (&from == this) return; Clear(); MergeFrom(from); @@ -1353,6 +1379,7 @@ void CodeGeneratorResponse_File::clear_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()); } @@ -1406,6 +1433,7 @@ void CodeGeneratorResponse_File::clear_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()); } @@ -1459,6 +1487,7 @@ void CodeGeneratorResponse_File::clear_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()); } @@ -1516,6 +1545,7 @@ void CodeGeneratorResponse::clear_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()); } diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index 0a03e979..510202f0 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -437,6 +437,7 @@ inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* va // @@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) return file_to_generate_.Add(); } inline void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) { @@ -502,6 +503,7 @@ inline ::std::string* CodeGeneratorRequest::mutable_parameter() { return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -589,6 +591,7 @@ inline ::std::string* CodeGeneratorResponse_File::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -642,6 +645,7 @@ inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() { return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -695,6 +699,7 @@ inline ::std::string* CodeGeneratorResponse_File::mutable_content() { return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -752,6 +757,7 @@ inline ::std::string* CodeGeneratorResponse::mutable_error() { return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc index e82bbae7..23f2449c 100644 --- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc +++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc @@ -44,9 +44,10 @@ #include <google/protobuf/io/zero_copy_stream.h> #include <google/protobuf/io/printer.h> +#include <google/protobuf/testing/file.h> +#include <google/protobuf/testing/file.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> -#include <google/protobuf/testing/file.h> namespace google { namespace protobuf { diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index 78a34617..56e11fa9 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -357,13 +357,20 @@ void DeleteAllowedProto3Extendee() { void InitAllowedProto3Extendee() { allowed_proto3_extendees_ = new set<string>; - allowed_proto3_extendees_->insert("google.protobuf.FileOptions"); - allowed_proto3_extendees_->insert("google.protobuf.MessageOptions"); - allowed_proto3_extendees_->insert("google.protobuf.FieldOptions"); - allowed_proto3_extendees_->insert("google.protobuf.EnumOptions"); - allowed_proto3_extendees_->insert("google.protobuf.EnumValueOptions"); - allowed_proto3_extendees_->insert("google.protobuf.ServiceOptions"); - allowed_proto3_extendees_->insert("google.protobuf.MethodOptions"); + const char* kOptionNames[] = { + "FileOptions", "MessageOptions", "FieldOptions", "EnumOptions", + "EnumValueOptions", "ServiceOptions", "MethodOptions"}; + for (int i = 0; i < GOOGLE_ARRAYSIZE(kOptionNames); ++i) { + // 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]); + // 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]); + } + google::protobuf::internal::OnShutdown(&DeleteAllowedProto3Extendee); } @@ -2766,6 +2773,9 @@ class DescriptorBuilder { private: friend class OptionInterpreter; + // Non-recursive part of BuildFile functionality. + const FileDescriptor* BuildFileImpl(const FileDescriptorProto& proto); + const DescriptorPool* pool_; DescriptorPool::Tables* tables_; // for convenience DescriptorPool::ErrorCollector* error_collector_; @@ -3834,7 +3844,11 @@ 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(); @@ -5113,11 +5127,6 @@ void DescriptorBuilder::ValidateProto3( for (int i = 0; i < file->enum_type_count(); ++i) { ValidateProto3Enum(file->enum_types_ + i, proto.enum_type(i)); } - if (IsLite(file)) { - AddError(file->name(), proto, - DescriptorPool::ErrorCollector::OTHER, - "Lite runtime is not supported in proto3."); - } } static string ToLowercaseWithoutUnderscores(const string& name) { diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 1338537e..4d5c4d99 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -944,6 +944,7 @@ FileDescriptorSet* FileDescriptorSet::New(::google::protobuf::Arena* arena) cons } void FileDescriptorSet::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorSet) file_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); if (_internal_metadata_.have_unknown_fields()) { @@ -953,7 +954,7 @@ void FileDescriptorSet::Clear() { bool FileDescriptorSet::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.FileDescriptorSet) for (;;) { @@ -1034,6 +1035,7 @@ void FileDescriptorSet::SerializeWithCachedSizes( } int FileDescriptorSet::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorSet) int total_size = 0; // repeated .google.protobuf.FileDescriptorProto file = 1; @@ -1056,18 +1058,22 @@ int FileDescriptorSet::ByteSize() const { } void FileDescriptorSet::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileDescriptorSet) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const FileDescriptorSet* source = ::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorSet>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FileDescriptorSet) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FileDescriptorSet) MergeFrom(*source); } } void FileDescriptorSet::MergeFrom(const FileDescriptorSet& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorSet) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); file_.MergeFrom(from.file_); if (from._internal_metadata_.have_unknown_fields()) { @@ -1076,12 +1082,14 @@ void FileDescriptorSet::MergeFrom(const FileDescriptorSet& from) { } void FileDescriptorSet::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FileDescriptorSet) if (&from == this) return; Clear(); MergeFrom(from); } void FileDescriptorSet::CopyFrom(const FileDescriptorSet& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FileDescriptorSet) if (&from == this) return; Clear(); MergeFrom(from); @@ -1235,6 +1243,7 @@ FileDescriptorProto* FileDescriptorProto::New(::google::protobuf::Arena* arena) } void FileDescriptorProto::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorProto) if (_has_bits_[0 / 32] & 3u) { if (has_name()) { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); @@ -1269,7 +1278,7 @@ void FileDescriptorProto::Clear() { bool FileDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.FileDescriptorProto) for (;;) { @@ -1704,6 +1713,7 @@ void FileDescriptorProto::SerializeWithCachedSizes( } int FileDescriptorProto::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorProto) int total_size = 0; if (_has_bits_[0 / 32] & 3u) { @@ -1816,18 +1826,22 @@ int FileDescriptorProto::ByteSize() const { } void FileDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileDescriptorProto) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const FileDescriptorProto* source = ::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorProto>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FileDescriptorProto) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FileDescriptorProto) MergeFrom(*source); } } void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorProto) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); dependency_.MergeFrom(from.dependency_); public_dependency_.MergeFrom(from.public_dependency_); @@ -1864,12 +1878,14 @@ void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) { } void FileDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FileDescriptorProto) if (&from == this) return; Clear(); MergeFrom(from); } void FileDescriptorProto::CopyFrom(const FileDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FileDescriptorProto) if (&from == this) return; Clear(); MergeFrom(from); @@ -1960,6 +1976,7 @@ void FileDescriptorProto::clear_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()); } @@ -2013,6 +2030,7 @@ void FileDescriptorProto::clear_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()); } @@ -2055,6 +2073,7 @@ void FileDescriptorProto::clear_dependency() { // @@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) { @@ -2287,6 +2306,7 @@ const ::google::protobuf::FileOptions& FileDescriptorProto::options() const { 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; @@ -2330,6 +2350,7 @@ const ::google::protobuf::SourceCodeInfo& 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; @@ -2386,6 +2407,7 @@ void FileDescriptorProto::clear_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()); } @@ -2468,8 +2490,17 @@ DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::New(::google::pr } void DescriptorProto_ExtensionRange::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ExtensionRange) +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(DescriptorProto_ExtensionRange, f) \ + _Pragma("clang diagnostic pop") +#else #define ZR_HELPER_(f) reinterpret_cast<char*>(\ &reinterpret_cast<DescriptorProto_ExtensionRange*>(16)->f) +#endif #define ZR_(first, last) do {\ ::memset(&first, 0,\ @@ -2489,7 +2520,7 @@ void DescriptorProto_ExtensionRange::Clear() { bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto.ExtensionRange) for (;;) { @@ -2590,6 +2621,7 @@ void DescriptorProto_ExtensionRange::SerializeWithCachedSizes( } int DescriptorProto_ExtensionRange::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ExtensionRange) int total_size = 0; if (_has_bits_[0 / 32] & 3u) { @@ -2620,18 +2652,22 @@ int DescriptorProto_ExtensionRange::ByteSize() const { } void DescriptorProto_ExtensionRange::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto.ExtensionRange) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const DescriptorProto_ExtensionRange* source = ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto_ExtensionRange>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DescriptorProto.ExtensionRange) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DescriptorProto.ExtensionRange) MergeFrom(*source); } } void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRange& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ExtensionRange) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_start()) { @@ -2647,12 +2683,14 @@ void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRa } void DescriptorProto_ExtensionRange::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DescriptorProto.ExtensionRange) if (&from == this) return; Clear(); MergeFrom(from); } void DescriptorProto_ExtensionRange::CopyFrom(const DescriptorProto_ExtensionRange& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.DescriptorProto.ExtensionRange) if (&from == this) return; Clear(); MergeFrom(from); @@ -2751,8 +2789,17 @@ DescriptorProto_ReservedRange* DescriptorProto_ReservedRange::New(::google::prot } void DescriptorProto_ReservedRange::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ReservedRange) +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(DescriptorProto_ReservedRange, f) \ + _Pragma("clang diagnostic pop") +#else #define ZR_HELPER_(f) reinterpret_cast<char*>(\ &reinterpret_cast<DescriptorProto_ReservedRange*>(16)->f) +#endif #define ZR_(first, last) do {\ ::memset(&first, 0,\ @@ -2772,7 +2819,7 @@ void DescriptorProto_ReservedRange::Clear() { bool DescriptorProto_ReservedRange::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto.ReservedRange) for (;;) { @@ -2873,6 +2920,7 @@ void DescriptorProto_ReservedRange::SerializeWithCachedSizes( } int DescriptorProto_ReservedRange::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ReservedRange) int total_size = 0; if (_has_bits_[0 / 32] & 3u) { @@ -2903,18 +2951,22 @@ int DescriptorProto_ReservedRange::ByteSize() const { } void DescriptorProto_ReservedRange::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto.ReservedRange) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const DescriptorProto_ReservedRange* source = ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto_ReservedRange>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DescriptorProto.ReservedRange) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DescriptorProto.ReservedRange) MergeFrom(*source); } } void DescriptorProto_ReservedRange::MergeFrom(const DescriptorProto_ReservedRange& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ReservedRange) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_start()) { @@ -2930,12 +2982,14 @@ void DescriptorProto_ReservedRange::MergeFrom(const DescriptorProto_ReservedRang } void DescriptorProto_ReservedRange::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DescriptorProto.ReservedRange) if (&from == this) return; Clear(); MergeFrom(from); } void DescriptorProto_ReservedRange::CopyFrom(const DescriptorProto_ReservedRange& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.DescriptorProto.ReservedRange) if (&from == this) return; Clear(); MergeFrom(from); @@ -3046,6 +3100,7 @@ DescriptorProto* DescriptorProto::New(::google::protobuf::Arena* arena) const { } void DescriptorProto::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto) if (_has_bits_[0 / 32] & 129u) { if (has_name()) { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); @@ -3070,7 +3125,7 @@ void DescriptorProto::Clear() { bool DescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto) for (;;) { @@ -3429,6 +3484,7 @@ void DescriptorProto::SerializeWithCachedSizes( } int DescriptorProto::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto) int total_size = 0; if (_has_bits_[0 / 32] & 129u) { @@ -3522,18 +3578,22 @@ int DescriptorProto::ByteSize() const { } void DescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const DescriptorProto* source = ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DescriptorProto) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DescriptorProto) MergeFrom(*source); } } void DescriptorProto::MergeFrom(const DescriptorProto& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); field_.MergeFrom(from.field_); extension_.MergeFrom(from.extension_); @@ -3558,12 +3618,14 @@ void DescriptorProto::MergeFrom(const DescriptorProto& from) { } void DescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DescriptorProto) if (&from == this) return; Clear(); MergeFrom(from); } void DescriptorProto::CopyFrom(const DescriptorProto& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.DescriptorProto) if (&from == this) return; Clear(); MergeFrom(from); @@ -3756,6 +3818,7 @@ void DescriptorProto::clear_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()); } @@ -3976,6 +4039,7 @@ const ::google::protobuf::MessageOptions& DescriptorProto::options() const { 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; @@ -4051,6 +4115,7 @@ void DescriptorProto::clear_reserved_name() { // @@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) { @@ -4245,6 +4310,7 @@ FieldDescriptorProto* FieldDescriptorProto::New(::google::protobuf::Arena* arena } void FieldDescriptorProto::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.FieldDescriptorProto) if (_has_bits_[0 / 32] & 255u) { if (has_name()) { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); @@ -4279,7 +4345,7 @@ void FieldDescriptorProto::Clear() { bool FieldDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.FieldDescriptorProto) for (;;) { @@ -4660,6 +4726,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes( } int FieldDescriptorProto::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldDescriptorProto) int total_size = 0; if (_has_bits_[0 / 32] & 255u) { @@ -4746,18 +4813,22 @@ int FieldDescriptorProto::ByteSize() const { } void FieldDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldDescriptorProto) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const FieldDescriptorProto* source = ::google::protobuf::internal::DynamicCastToGenerated<const FieldDescriptorProto>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FieldDescriptorProto) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FieldDescriptorProto) MergeFrom(*source); } } void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldDescriptorProto) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_name()) { @@ -4804,12 +4875,14 @@ void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) { } void FieldDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FieldDescriptorProto) if (&from == this) return; Clear(); MergeFrom(from); } void FieldDescriptorProto::CopyFrom(const FieldDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FieldDescriptorProto) if (&from == this) return; Clear(); MergeFrom(from); @@ -4894,6 +4967,7 @@ void FieldDescriptorProto::clear_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()); } @@ -5021,6 +5095,7 @@ void FieldDescriptorProto::clear_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()); } @@ -5074,6 +5149,7 @@ void FieldDescriptorProto::clear_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()); } @@ -5127,6 +5203,7 @@ void FieldDescriptorProto::clear_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()); } @@ -5204,6 +5281,7 @@ void FieldDescriptorProto::clear_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()); } @@ -5244,6 +5322,7 @@ const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const { 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; @@ -5329,6 +5408,7 @@ OneofDescriptorProto* OneofDescriptorProto::New(::google::protobuf::Arena* arena } void OneofDescriptorProto::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.OneofDescriptorProto) if (has_name()) { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -5340,7 +5420,7 @@ void OneofDescriptorProto::Clear() { bool OneofDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.OneofDescriptorProto) for (;;) { @@ -5429,6 +5509,7 @@ void OneofDescriptorProto::SerializeWithCachedSizes( } int OneofDescriptorProto::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.OneofDescriptorProto) int total_size = 0; // optional string name = 1; @@ -5450,18 +5531,22 @@ int OneofDescriptorProto::ByteSize() const { } void OneofDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.OneofDescriptorProto) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const OneofDescriptorProto* source = ::google::protobuf::internal::DynamicCastToGenerated<const OneofDescriptorProto>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.OneofDescriptorProto) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.OneofDescriptorProto) MergeFrom(*source); } } void OneofDescriptorProto::MergeFrom(const OneofDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.OneofDescriptorProto) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_name()) { @@ -5475,12 +5560,14 @@ void OneofDescriptorProto::MergeFrom(const OneofDescriptorProto& from) { } void OneofDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.OneofDescriptorProto) if (&from == this) return; Clear(); MergeFrom(from); } void OneofDescriptorProto::CopyFrom(const OneofDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.OneofDescriptorProto) if (&from == this) return; Clear(); MergeFrom(from); @@ -5553,6 +5640,7 @@ void OneofDescriptorProto::clear_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()); } @@ -5640,6 +5728,7 @@ EnumDescriptorProto* EnumDescriptorProto::New(::google::protobuf::Arena* arena) } void EnumDescriptorProto::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumDescriptorProto) if (_has_bits_[0 / 32] & 5u) { if (has_name()) { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); @@ -5657,7 +5746,7 @@ void EnumDescriptorProto::Clear() { bool EnumDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.EnumDescriptorProto) for (;;) { @@ -5802,6 +5891,7 @@ void EnumDescriptorProto::SerializeWithCachedSizes( } int EnumDescriptorProto::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumDescriptorProto) int total_size = 0; if (_has_bits_[0 / 32] & 5u) { @@ -5840,18 +5930,22 @@ int EnumDescriptorProto::ByteSize() const { } void EnumDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumDescriptorProto) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const EnumDescriptorProto* source = ::google::protobuf::internal::DynamicCastToGenerated<const EnumDescriptorProto>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumDescriptorProto) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumDescriptorProto) MergeFrom(*source); } } void EnumDescriptorProto::MergeFrom(const EnumDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumDescriptorProto) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); value_.MergeFrom(from.value_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { @@ -5869,12 +5963,14 @@ void EnumDescriptorProto::MergeFrom(const EnumDescriptorProto& from) { } void EnumDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumDescriptorProto) if (&from == this) return; Clear(); MergeFrom(from); } void EnumDescriptorProto::CopyFrom(const EnumDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumDescriptorProto) if (&from == this) return; Clear(); MergeFrom(from); @@ -5953,6 +6049,7 @@ void EnumDescriptorProto::clear_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()); } @@ -6023,6 +6120,7 @@ const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const { 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; @@ -6114,6 +6212,7 @@ EnumValueDescriptorProto* EnumValueDescriptorProto::New(::google::protobuf::Aren } void EnumValueDescriptorProto::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueDescriptorProto) if (_has_bits_[0 / 32] & 7u) { if (has_name()) { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); @@ -6131,7 +6230,7 @@ void EnumValueDescriptorProto::Clear() { bool EnumValueDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.EnumValueDescriptorProto) for (;;) { @@ -6271,6 +6370,7 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes( } int EnumValueDescriptorProto::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValueDescriptorProto) int total_size = 0; if (_has_bits_[0 / 32] & 7u) { @@ -6308,18 +6408,22 @@ int EnumValueDescriptorProto::ByteSize() const { } void EnumValueDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValueDescriptorProto) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const EnumValueDescriptorProto* source = ::google::protobuf::internal::DynamicCastToGenerated<const EnumValueDescriptorProto>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumValueDescriptorProto) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumValueDescriptorProto) MergeFrom(*source); } } void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueDescriptorProto) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_name()) { @@ -6339,12 +6443,14 @@ void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) { } void EnumValueDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumValueDescriptorProto) if (&from == this) return; Clear(); MergeFrom(from); } void EnumValueDescriptorProto::CopyFrom(const EnumValueDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumValueDescriptorProto) if (&from == this) return; Clear(); MergeFrom(from); @@ -6422,6 +6528,7 @@ void EnumValueDescriptorProto::clear_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()); } @@ -6486,6 +6593,7 @@ const ::google::protobuf::EnumValueOptions& 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; @@ -6576,6 +6684,7 @@ ServiceDescriptorProto* ServiceDescriptorProto::New(::google::protobuf::Arena* a } void ServiceDescriptorProto::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceDescriptorProto) if (_has_bits_[0 / 32] & 5u) { if (has_name()) { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); @@ -6593,7 +6702,7 @@ void ServiceDescriptorProto::Clear() { bool ServiceDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.ServiceDescriptorProto) for (;;) { @@ -6738,6 +6847,7 @@ void ServiceDescriptorProto::SerializeWithCachedSizes( } int ServiceDescriptorProto::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ServiceDescriptorProto) int total_size = 0; if (_has_bits_[0 / 32] & 5u) { @@ -6776,18 +6886,22 @@ int ServiceDescriptorProto::ByteSize() const { } void ServiceDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ServiceDescriptorProto) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const ServiceDescriptorProto* source = ::google::protobuf::internal::DynamicCastToGenerated<const ServiceDescriptorProto>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ServiceDescriptorProto) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ServiceDescriptorProto) MergeFrom(*source); } } void ServiceDescriptorProto::MergeFrom(const ServiceDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceDescriptorProto) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); method_.MergeFrom(from.method_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { @@ -6805,12 +6919,14 @@ void ServiceDescriptorProto::MergeFrom(const ServiceDescriptorProto& from) { } void ServiceDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ServiceDescriptorProto) if (&from == this) return; Clear(); MergeFrom(from); } void ServiceDescriptorProto::CopyFrom(const ServiceDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.ServiceDescriptorProto) if (&from == this) return; Clear(); MergeFrom(from); @@ -6889,6 +7005,7 @@ void ServiceDescriptorProto::clear_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()); } @@ -6959,6 +7076,7 @@ const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() cons 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; @@ -7058,8 +7176,17 @@ MethodDescriptorProto* MethodDescriptorProto::New(::google::protobuf::Arena* are } void MethodDescriptorProto::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.MethodDescriptorProto) +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(MethodDescriptorProto, f) \ + _Pragma("clang diagnostic pop") +#else #define ZR_HELPER_(f) reinterpret_cast<char*>(\ &reinterpret_cast<MethodDescriptorProto*>(16)->f) +#endif #define ZR_(first, last) do {\ ::memset(&first, 0,\ @@ -7093,7 +7220,7 @@ void MethodDescriptorProto::Clear() { bool MethodDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.MethodDescriptorProto) for (;;) { @@ -7334,6 +7461,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes( } int MethodDescriptorProto::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.MethodDescriptorProto) int total_size = 0; if (_has_bits_[0 / 32] & 63u) { @@ -7388,18 +7516,22 @@ int MethodDescriptorProto::ByteSize() const { } void MethodDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MethodDescriptorProto) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const MethodDescriptorProto* source = ::google::protobuf::internal::DynamicCastToGenerated<const MethodDescriptorProto>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.MethodDescriptorProto) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.MethodDescriptorProto) MergeFrom(*source); } } void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodDescriptorProto) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_name()) { @@ -7430,12 +7562,14 @@ void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) { } void MethodDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.MethodDescriptorProto) if (&from == this) return; Clear(); MergeFrom(from); } void MethodDescriptorProto::CopyFrom(const MethodDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.MethodDescriptorProto) if (&from == this) return; Clear(); MergeFrom(from); @@ -7516,6 +7650,7 @@ void MethodDescriptorProto::clear_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()); } @@ -7569,6 +7704,7 @@ void MethodDescriptorProto::clear_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()); } @@ -7622,6 +7758,7 @@ void MethodDescriptorProto::clear_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()); } @@ -7662,6 +7799,7 @@ const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const 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; @@ -7849,9 +7987,18 @@ FileOptions* FileOptions::New(::google::protobuf::Arena* arena) const { } void FileOptions::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.FileOptions) _extensions_.Clear(); +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(FileOptions, f) \ + _Pragma("clang diagnostic pop") +#else #define ZR_HELPER_(f) reinterpret_cast<char*>(\ &reinterpret_cast<FileOptions*>(16)->f) +#endif #define ZR_(first, last) do {\ ::memset(&first, 0,\ @@ -7893,7 +8040,7 @@ void FileOptions::Clear() { bool FileOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.FileOptions) for (;;) { @@ -8409,6 +8556,7 @@ void FileOptions::SerializeWithCachedSizes( } int FileOptions::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileOptions) int total_size = 0; if (_has_bits_[0 / 32] & 255u) { @@ -8518,18 +8666,22 @@ int FileOptions::ByteSize() const { } void FileOptions::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileOptions) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const FileOptions* source = ::google::protobuf::internal::DynamicCastToGenerated<const FileOptions>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FileOptions) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FileOptions) MergeFrom(*source); } } void FileOptions::MergeFrom(const FileOptions& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileOptions) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { @@ -8590,12 +8742,14 @@ void FileOptions::MergeFrom(const FileOptions& from) { } void FileOptions::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FileOptions) if (&from == this) return; Clear(); MergeFrom(from); } void FileOptions::CopyFrom(const FileOptions& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FileOptions) if (&from == this) return; Clear(); MergeFrom(from); @@ -8685,6 +8839,7 @@ void FileOptions::clear_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()); } @@ -8738,6 +8893,7 @@ void FileOptions::clear_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()); } @@ -8888,6 +9044,7 @@ void FileOptions::clear_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()); } @@ -9061,6 +9218,7 @@ void FileOptions::clear_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()); } @@ -9114,6 +9272,7 @@ void FileOptions::clear_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()); } @@ -9231,9 +9390,18 @@ MessageOptions* MessageOptions::New(::google::protobuf::Arena* arena) const { } void MessageOptions::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.MessageOptions) _extensions_.Clear(); +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(MessageOptions, f) \ + _Pragma("clang diagnostic pop") +#else #define ZR_HELPER_(f) reinterpret_cast<char*>(\ &reinterpret_cast<MessageOptions*>(16)->f) +#endif #define ZR_(first, last) do {\ ::memset(&first, 0,\ @@ -9254,7 +9422,7 @@ void MessageOptions::Clear() { bool MessageOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.MessageOptions) for (;;) { @@ -9448,6 +9616,7 @@ void MessageOptions::SerializeWithCachedSizes( } int MessageOptions::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.MessageOptions) int total_size = 0; if (_has_bits_[0 / 32] & 15u) { @@ -9494,18 +9663,22 @@ int MessageOptions::ByteSize() const { } void MessageOptions::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MessageOptions) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const MessageOptions* source = ::google::protobuf::internal::DynamicCastToGenerated<const MessageOptions>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.MessageOptions) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.MessageOptions) MergeFrom(*source); } } void MessageOptions::MergeFrom(const MessageOptions& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MessageOptions) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { @@ -9529,12 +9702,14 @@ void MessageOptions::MergeFrom(const MessageOptions& from) { } void MessageOptions::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.MessageOptions) if (&from == this) return; Clear(); MergeFrom(from); } void MessageOptions::CopyFrom(const MessageOptions& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.MessageOptions) if (&from == this) return; Clear(); MergeFrom(from); @@ -9824,9 +9999,18 @@ FieldOptions* FieldOptions::New(::google::protobuf::Arena* arena) const { } void FieldOptions::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.FieldOptions) _extensions_.Clear(); +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(FieldOptions, f) \ + _Pragma("clang diagnostic pop") +#else #define ZR_HELPER_(f) reinterpret_cast<char*>(\ &reinterpret_cast<FieldOptions*>(16)->f) +#endif #define ZR_(first, last) do {\ ::memset(&first, 0,\ @@ -9850,7 +10034,7 @@ void FieldOptions::Clear() { bool FieldOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.FieldOptions) for (;;) { @@ -10108,6 +10292,7 @@ void FieldOptions::SerializeWithCachedSizes( } int FieldOptions::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldOptions) int total_size = 0; if (_has_bits_[0 / 32] & 63u) { @@ -10166,18 +10351,22 @@ int FieldOptions::ByteSize() const { } void FieldOptions::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldOptions) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const FieldOptions* source = ::google::protobuf::internal::DynamicCastToGenerated<const FieldOptions>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FieldOptions) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FieldOptions) MergeFrom(*source); } } void FieldOptions::MergeFrom(const FieldOptions& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldOptions) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { @@ -10207,12 +10396,14 @@ void FieldOptions::MergeFrom(const FieldOptions& from) { } void FieldOptions::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FieldOptions) if (&from == this) return; Clear(); MergeFrom(from); } void FieldOptions::CopyFrom(const FieldOptions& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FieldOptions) if (&from == this) return; Clear(); MergeFrom(from); @@ -10500,9 +10691,18 @@ EnumOptions* EnumOptions::New(::google::protobuf::Arena* arena) const { } void EnumOptions::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumOptions) _extensions_.Clear(); +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(EnumOptions, f) \ + _Pragma("clang diagnostic pop") +#else #define ZR_HELPER_(f) reinterpret_cast<char*>(\ &reinterpret_cast<EnumOptions*>(16)->f) +#endif #define ZR_(first, last) do {\ ::memset(&first, 0,\ @@ -10523,7 +10723,7 @@ void EnumOptions::Clear() { bool EnumOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.EnumOptions) for (;;) { @@ -10667,6 +10867,7 @@ void EnumOptions::SerializeWithCachedSizes( } int EnumOptions::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumOptions) int total_size = 0; if (_has_bits_[0 / 32] & 3u) { @@ -10703,18 +10904,22 @@ int EnumOptions::ByteSize() const { } void EnumOptions::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumOptions) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const EnumOptions* source = ::google::protobuf::internal::DynamicCastToGenerated<const EnumOptions>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumOptions) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumOptions) MergeFrom(*source); } } void EnumOptions::MergeFrom(const EnumOptions& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumOptions) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { @@ -10732,12 +10937,14 @@ void EnumOptions::MergeFrom(const EnumOptions& from) { } void EnumOptions::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumOptions) if (&from == this) return; Clear(); MergeFrom(from); } void EnumOptions::CopyFrom(const EnumOptions& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumOptions) if (&from == this) return; Clear(); MergeFrom(from); @@ -10921,6 +11128,7 @@ EnumValueOptions* EnumValueOptions::New(::google::protobuf::Arena* arena) const } void EnumValueOptions::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueOptions) _extensions_.Clear(); deprecated_ = false; uninterpreted_option_.Clear(); @@ -10932,7 +11140,7 @@ void EnumValueOptions::Clear() { bool EnumValueOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.EnumValueOptions) for (;;) { @@ -11051,6 +11259,7 @@ void EnumValueOptions::SerializeWithCachedSizes( } int EnumValueOptions::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValueOptions) int total_size = 0; // optional bool deprecated = 1 [default = false]; @@ -11080,18 +11289,22 @@ int EnumValueOptions::ByteSize() const { } void EnumValueOptions::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValueOptions) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const EnumValueOptions* source = ::google::protobuf::internal::DynamicCastToGenerated<const EnumValueOptions>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumValueOptions) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumValueOptions) MergeFrom(*source); } } void EnumValueOptions::MergeFrom(const EnumValueOptions& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueOptions) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { @@ -11106,12 +11319,14 @@ void EnumValueOptions::MergeFrom(const EnumValueOptions& from) { } void EnumValueOptions::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumValueOptions) if (&from == this) return; Clear(); MergeFrom(from); } void EnumValueOptions::CopyFrom(const EnumValueOptions& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumValueOptions) if (&from == this) return; Clear(); MergeFrom(from); @@ -11270,6 +11485,7 @@ ServiceOptions* ServiceOptions::New(::google::protobuf::Arena* arena) const { } void ServiceOptions::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceOptions) _extensions_.Clear(); deprecated_ = false; uninterpreted_option_.Clear(); @@ -11281,7 +11497,7 @@ void ServiceOptions::Clear() { bool ServiceOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.ServiceOptions) for (;;) { @@ -11400,6 +11616,7 @@ void ServiceOptions::SerializeWithCachedSizes( } int ServiceOptions::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ServiceOptions) int total_size = 0; // optional bool deprecated = 33 [default = false]; @@ -11429,18 +11646,22 @@ int ServiceOptions::ByteSize() const { } void ServiceOptions::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ServiceOptions) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const ServiceOptions* source = ::google::protobuf::internal::DynamicCastToGenerated<const ServiceOptions>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ServiceOptions) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ServiceOptions) MergeFrom(*source); } } void ServiceOptions::MergeFrom(const ServiceOptions& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceOptions) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { @@ -11455,12 +11676,14 @@ void ServiceOptions::MergeFrom(const ServiceOptions& from) { } void ServiceOptions::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ServiceOptions) if (&from == this) return; Clear(); MergeFrom(from); } void ServiceOptions::CopyFrom(const ServiceOptions& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.ServiceOptions) if (&from == this) return; Clear(); MergeFrom(from); @@ -11619,6 +11842,7 @@ MethodOptions* MethodOptions::New(::google::protobuf::Arena* arena) const { } void MethodOptions::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.MethodOptions) _extensions_.Clear(); deprecated_ = false; uninterpreted_option_.Clear(); @@ -11630,7 +11854,7 @@ void MethodOptions::Clear() { bool MethodOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.MethodOptions) for (;;) { @@ -11749,6 +11973,7 @@ void MethodOptions::SerializeWithCachedSizes( } int MethodOptions::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.MethodOptions) int total_size = 0; // optional bool deprecated = 33 [default = false]; @@ -11778,18 +12003,22 @@ int MethodOptions::ByteSize() const { } void MethodOptions::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MethodOptions) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const MethodOptions* source = ::google::protobuf::internal::DynamicCastToGenerated<const MethodOptions>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.MethodOptions) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.MethodOptions) MergeFrom(*source); } } void MethodOptions::MergeFrom(const MethodOptions& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodOptions) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { @@ -11804,12 +12033,14 @@ void MethodOptions::MergeFrom(const MethodOptions& from) { } void MethodOptions::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.MethodOptions) if (&from == this) return; Clear(); MergeFrom(from); } void MethodOptions::CopyFrom(const MethodOptions& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.MethodOptions) if (&from == this) return; Clear(); MergeFrom(from); @@ -11971,6 +12202,7 @@ UninterpretedOption_NamePart* UninterpretedOption_NamePart::New(::google::protob } void UninterpretedOption_NamePart::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption.NamePart) if (_has_bits_[0 / 32] & 3u) { if (has_name_part()) { name_part_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); @@ -11985,7 +12217,7 @@ void UninterpretedOption_NamePart::Clear() { bool UninterpretedOption_NamePart::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.UninterpretedOption.NamePart) for (;;) { @@ -12099,6 +12331,7 @@ void UninterpretedOption_NamePart::SerializeWithCachedSizes( } int UninterpretedOption_NamePart::RequiredFieldsByteSizeFallback() const { +// @@protoc_insertion_point(required_fields_byte_size_fallback_start:google.protobuf.UninterpretedOption.NamePart) int total_size = 0; if (has_name_part()) { @@ -12116,6 +12349,7 @@ int UninterpretedOption_NamePart::RequiredFieldsByteSizeFallback() const { return total_size; } int UninterpretedOption_NamePart::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption.NamePart) int total_size = 0; if (((_has_bits_[0] & 0x00000003) ^ 0x00000003) == 0) { // All required fields are present. @@ -12142,18 +12376,22 @@ int UninterpretedOption_NamePart::ByteSize() const { } void UninterpretedOption_NamePart::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UninterpretedOption.NamePart) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const UninterpretedOption_NamePart* source = ::google::protobuf::internal::DynamicCastToGenerated<const UninterpretedOption_NamePart>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UninterpretedOption.NamePart) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UninterpretedOption.NamePart) MergeFrom(*source); } } void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption.NamePart) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_name_part()) { @@ -12170,12 +12408,14 @@ void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart& } void UninterpretedOption_NamePart::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UninterpretedOption.NamePart) if (&from == this) return; Clear(); MergeFrom(from); } void UninterpretedOption_NamePart::CopyFrom(const UninterpretedOption_NamePart& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.UninterpretedOption.NamePart) if (&from == this) return; Clear(); MergeFrom(from); @@ -12288,8 +12528,17 @@ UninterpretedOption* UninterpretedOption::New(::google::protobuf::Arena* arena) } void UninterpretedOption::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption) +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(UninterpretedOption, f) \ + _Pragma("clang diagnostic pop") +#else #define ZR_HELPER_(f) reinterpret_cast<char*>(\ &reinterpret_cast<UninterpretedOption*>(16)->f) +#endif #define ZR_(first, last) do {\ ::memset(&first, 0,\ @@ -12321,7 +12570,7 @@ void UninterpretedOption::Clear() { bool UninterpretedOption::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.UninterpretedOption) for (;;) { @@ -12579,6 +12828,7 @@ void UninterpretedOption::SerializeWithCachedSizes( } int UninterpretedOption::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption) int total_size = 0; if (_has_bits_[1 / 32] & 126u) { @@ -12643,18 +12893,22 @@ int UninterpretedOption::ByteSize() const { } void UninterpretedOption::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UninterpretedOption) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const UninterpretedOption* source = ::google::protobuf::internal::DynamicCastToGenerated<const UninterpretedOption>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UninterpretedOption) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UninterpretedOption) MergeFrom(*source); } } void UninterpretedOption::MergeFrom(const UninterpretedOption& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); name_.MergeFrom(from.name_); if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) { @@ -12686,12 +12940,14 @@ void UninterpretedOption::MergeFrom(const UninterpretedOption& from) { } void UninterpretedOption::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UninterpretedOption) if (&from == this) return; Clear(); MergeFrom(from); } void UninterpretedOption::CopyFrom(const UninterpretedOption& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.UninterpretedOption) if (&from == this) return; Clear(); MergeFrom(from); @@ -12771,6 +13027,7 @@ void UninterpretedOption_NamePart::clear_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()); } @@ -12882,6 +13139,7 @@ void UninterpretedOption::clear_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()); } @@ -13007,6 +13265,7 @@ void UninterpretedOption::clear_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()); } @@ -13060,6 +13319,7 @@ void UninterpretedOption::clear_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()); } @@ -13148,6 +13408,7 @@ SourceCodeInfo_Location* SourceCodeInfo_Location::New(::google::protobuf::Arena* } void SourceCodeInfo_Location::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo.Location) if (_has_bits_[0 / 32] & 12u) { if (has_leading_comments()) { leading_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); @@ -13167,7 +13428,7 @@ void SourceCodeInfo_Location::Clear() { bool SourceCodeInfo_Location::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.SourceCodeInfo.Location) for (;;) { @@ -13417,6 +13678,7 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes( } int SourceCodeInfo_Location::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo.Location) int total_size = 0; if (_has_bits_[2 / 32] & 12u) { @@ -13488,18 +13750,22 @@ int SourceCodeInfo_Location::ByteSize() const { } void SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceCodeInfo.Location) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const SourceCodeInfo_Location* source = ::google::protobuf::internal::DynamicCastToGenerated<const SourceCodeInfo_Location>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.SourceCodeInfo.Location) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.SourceCodeInfo.Location) MergeFrom(*source); } } void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo.Location) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); path_.MergeFrom(from.path_); span_.MergeFrom(from.span_); @@ -13520,12 +13786,14 @@ void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) { } void SourceCodeInfo_Location::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.SourceCodeInfo.Location) if (&from == this) return; Clear(); MergeFrom(from); } void SourceCodeInfo_Location::CopyFrom(const SourceCodeInfo_Location& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.SourceCodeInfo.Location) if (&from == this) return; Clear(); MergeFrom(from); @@ -13624,6 +13892,7 @@ SourceCodeInfo* SourceCodeInfo::New(::google::protobuf::Arena* arena) const { } void SourceCodeInfo::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo) location_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); if (_internal_metadata_.have_unknown_fields()) { @@ -13633,7 +13902,7 @@ void SourceCodeInfo::Clear() { bool SourceCodeInfo::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.SourceCodeInfo) for (;;) { @@ -13714,6 +13983,7 @@ void SourceCodeInfo::SerializeWithCachedSizes( } int SourceCodeInfo::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo) int total_size = 0; // repeated .google.protobuf.SourceCodeInfo.Location location = 1; @@ -13736,18 +14006,22 @@ int SourceCodeInfo::ByteSize() const { } void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceCodeInfo) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const SourceCodeInfo* source = ::google::protobuf::internal::DynamicCastToGenerated<const SourceCodeInfo>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.SourceCodeInfo) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.SourceCodeInfo) MergeFrom(*source); } } void SourceCodeInfo::MergeFrom(const SourceCodeInfo& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); location_.MergeFrom(from.location_); if (from._internal_metadata_.have_unknown_fields()) { @@ -13756,12 +14030,14 @@ void SourceCodeInfo::MergeFrom(const SourceCodeInfo& from) { } void SourceCodeInfo::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.SourceCodeInfo) if (&from == this) return; Clear(); MergeFrom(from); } void SourceCodeInfo::CopyFrom(const SourceCodeInfo& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.SourceCodeInfo) if (&from == this) return; Clear(); MergeFrom(from); @@ -13894,6 +14170,7 @@ void SourceCodeInfo_Location::clear_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()); } @@ -13947,6 +14224,7 @@ void SourceCodeInfo_Location::clear_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()); } @@ -13989,6 +14267,7 @@ void SourceCodeInfo_Location::clear_leading_detached_comments() { // @@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) { @@ -14122,8 +14401,17 @@ GeneratedCodeInfo_Annotation* GeneratedCodeInfo_Annotation::New(::google::protob } void GeneratedCodeInfo_Annotation::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo.Annotation) +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(GeneratedCodeInfo_Annotation, f) \ + _Pragma("clang diagnostic pop") +#else #define ZR_HELPER_(f) reinterpret_cast<char*>(\ &reinterpret_cast<GeneratedCodeInfo_Annotation*>(16)->f) +#endif #define ZR_(first, last) do {\ ::memset(&first, 0,\ @@ -14149,7 +14437,7 @@ void GeneratedCodeInfo_Annotation::Clear() { bool GeneratedCodeInfo_Annotation::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.GeneratedCodeInfo.Annotation) for (;;) { @@ -14330,6 +14618,7 @@ void GeneratedCodeInfo_Annotation::SerializeWithCachedSizes( } int GeneratedCodeInfo_Annotation::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo.Annotation) int total_size = 0; if (_has_bits_[1 / 32] & 14u) { @@ -14384,18 +14673,22 @@ int GeneratedCodeInfo_Annotation::ByteSize() const { } void GeneratedCodeInfo_Annotation::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.GeneratedCodeInfo.Annotation) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const GeneratedCodeInfo_Annotation* source = ::google::protobuf::internal::DynamicCastToGenerated<const GeneratedCodeInfo_Annotation>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.GeneratedCodeInfo.Annotation) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.GeneratedCodeInfo.Annotation) MergeFrom(*source); } } void GeneratedCodeInfo_Annotation::MergeFrom(const GeneratedCodeInfo_Annotation& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo.Annotation) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); path_.MergeFrom(from.path_); if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) { @@ -14416,12 +14709,14 @@ void GeneratedCodeInfo_Annotation::MergeFrom(const GeneratedCodeInfo_Annotation& } void GeneratedCodeInfo_Annotation::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.GeneratedCodeInfo.Annotation) if (&from == this) return; Clear(); MergeFrom(from); } void GeneratedCodeInfo_Annotation::CopyFrom(const GeneratedCodeInfo_Annotation& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.GeneratedCodeInfo.Annotation) if (&from == this) return; Clear(); MergeFrom(from); @@ -14519,6 +14814,7 @@ GeneratedCodeInfo* GeneratedCodeInfo::New(::google::protobuf::Arena* arena) cons } void GeneratedCodeInfo::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo) annotation_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); if (_internal_metadata_.have_unknown_fields()) { @@ -14528,7 +14824,7 @@ void GeneratedCodeInfo::Clear() { bool GeneratedCodeInfo::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.GeneratedCodeInfo) for (;;) { @@ -14609,6 +14905,7 @@ void GeneratedCodeInfo::SerializeWithCachedSizes( } int GeneratedCodeInfo::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo) int total_size = 0; // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; @@ -14631,18 +14928,22 @@ int GeneratedCodeInfo::ByteSize() const { } void GeneratedCodeInfo::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.GeneratedCodeInfo) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const GeneratedCodeInfo* source = ::google::protobuf::internal::DynamicCastToGenerated<const GeneratedCodeInfo>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.GeneratedCodeInfo) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.GeneratedCodeInfo) MergeFrom(*source); } } void GeneratedCodeInfo::MergeFrom(const GeneratedCodeInfo& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); annotation_.MergeFrom(from.annotation_); if (from._internal_metadata_.have_unknown_fields()) { @@ -14651,12 +14952,14 @@ void GeneratedCodeInfo::MergeFrom(const GeneratedCodeInfo& from) { } void GeneratedCodeInfo::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.GeneratedCodeInfo) if (&from == this) return; Clear(); MergeFrom(from); } void GeneratedCodeInfo::CopyFrom(const GeneratedCodeInfo& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.GeneratedCodeInfo) if (&from == this) return; Clear(); MergeFrom(from); @@ -14759,6 +15062,7 @@ void GeneratedCodeInfo_Annotation::clear_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()); } diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index 9f15bf27..92a0a3a7 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -993,24 +993,42 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa // nested types ---------------------------------------------------- typedef FieldDescriptorProto_Type Type; - static const Type TYPE_DOUBLE = FieldDescriptorProto_Type_TYPE_DOUBLE; - static const Type TYPE_FLOAT = FieldDescriptorProto_Type_TYPE_FLOAT; - static const Type TYPE_INT64 = FieldDescriptorProto_Type_TYPE_INT64; - static const Type TYPE_UINT64 = FieldDescriptorProto_Type_TYPE_UINT64; - static const Type TYPE_INT32 = FieldDescriptorProto_Type_TYPE_INT32; - static const Type TYPE_FIXED64 = FieldDescriptorProto_Type_TYPE_FIXED64; - static const Type TYPE_FIXED32 = FieldDescriptorProto_Type_TYPE_FIXED32; - static const Type TYPE_BOOL = FieldDescriptorProto_Type_TYPE_BOOL; - static const Type TYPE_STRING = FieldDescriptorProto_Type_TYPE_STRING; - static const Type TYPE_GROUP = FieldDescriptorProto_Type_TYPE_GROUP; - static const Type TYPE_MESSAGE = FieldDescriptorProto_Type_TYPE_MESSAGE; - static const Type TYPE_BYTES = FieldDescriptorProto_Type_TYPE_BYTES; - static const Type TYPE_UINT32 = FieldDescriptorProto_Type_TYPE_UINT32; - static const Type TYPE_ENUM = FieldDescriptorProto_Type_TYPE_ENUM; - static const Type TYPE_SFIXED32 = FieldDescriptorProto_Type_TYPE_SFIXED32; - static const Type TYPE_SFIXED64 = FieldDescriptorProto_Type_TYPE_SFIXED64; - static const Type TYPE_SINT32 = FieldDescriptorProto_Type_TYPE_SINT32; - static const Type TYPE_SINT64 = FieldDescriptorProto_Type_TYPE_SINT64; + static const Type TYPE_DOUBLE = + FieldDescriptorProto_Type_TYPE_DOUBLE; + static const Type TYPE_FLOAT = + FieldDescriptorProto_Type_TYPE_FLOAT; + static const Type TYPE_INT64 = + FieldDescriptorProto_Type_TYPE_INT64; + static const Type TYPE_UINT64 = + FieldDescriptorProto_Type_TYPE_UINT64; + static const Type TYPE_INT32 = + FieldDescriptorProto_Type_TYPE_INT32; + static const Type TYPE_FIXED64 = + FieldDescriptorProto_Type_TYPE_FIXED64; + static const Type TYPE_FIXED32 = + FieldDescriptorProto_Type_TYPE_FIXED32; + static const Type TYPE_BOOL = + FieldDescriptorProto_Type_TYPE_BOOL; + static const Type TYPE_STRING = + FieldDescriptorProto_Type_TYPE_STRING; + static const Type TYPE_GROUP = + FieldDescriptorProto_Type_TYPE_GROUP; + static const Type TYPE_MESSAGE = + FieldDescriptorProto_Type_TYPE_MESSAGE; + static const Type TYPE_BYTES = + FieldDescriptorProto_Type_TYPE_BYTES; + static const Type TYPE_UINT32 = + FieldDescriptorProto_Type_TYPE_UINT32; + static const Type TYPE_ENUM = + FieldDescriptorProto_Type_TYPE_ENUM; + static const Type TYPE_SFIXED32 = + FieldDescriptorProto_Type_TYPE_SFIXED32; + static const Type TYPE_SFIXED64 = + FieldDescriptorProto_Type_TYPE_SFIXED64; + static const Type TYPE_SINT32 = + FieldDescriptorProto_Type_TYPE_SINT32; + static const Type TYPE_SINT64 = + FieldDescriptorProto_Type_TYPE_SINT64; static inline bool Type_IsValid(int value) { return FieldDescriptorProto_Type_IsValid(value); } @@ -1033,9 +1051,12 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa } typedef FieldDescriptorProto_Label Label; - static const Label LABEL_OPTIONAL = FieldDescriptorProto_Label_LABEL_OPTIONAL; - static const Label LABEL_REQUIRED = FieldDescriptorProto_Label_LABEL_REQUIRED; - static const Label LABEL_REPEATED = FieldDescriptorProto_Label_LABEL_REPEATED; + static const Label LABEL_OPTIONAL = + FieldDescriptorProto_Label_LABEL_OPTIONAL; + static const Label LABEL_REQUIRED = + FieldDescriptorProto_Label_LABEL_REQUIRED; + static const Label LABEL_REPEATED = + FieldDescriptorProto_Label_LABEL_REPEATED; static inline bool Label_IsValid(int value) { return FieldDescriptorProto_Label_IsValid(value); } @@ -1868,9 +1889,12 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { // nested types ---------------------------------------------------- typedef FileOptions_OptimizeMode OptimizeMode; - static const OptimizeMode SPEED = FileOptions_OptimizeMode_SPEED; - static const OptimizeMode CODE_SIZE = FileOptions_OptimizeMode_CODE_SIZE; - static const OptimizeMode LITE_RUNTIME = FileOptions_OptimizeMode_LITE_RUNTIME; + static const OptimizeMode SPEED = + FileOptions_OptimizeMode_SPEED; + static const OptimizeMode CODE_SIZE = + FileOptions_OptimizeMode_CODE_SIZE; + static const OptimizeMode LITE_RUNTIME = + FileOptions_OptimizeMode_LITE_RUNTIME; static inline bool OptimizeMode_IsValid(int value) { return FileOptions_OptimizeMode_IsValid(value); } @@ -2288,9 +2312,12 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { // nested types ---------------------------------------------------- typedef FieldOptions_CType CType; - static const CType STRING = FieldOptions_CType_STRING; - static const CType CORD = FieldOptions_CType_CORD; - static const CType STRING_PIECE = FieldOptions_CType_STRING_PIECE; + static const CType STRING = + FieldOptions_CType_STRING; + static const CType CORD = + FieldOptions_CType_CORD; + static const CType STRING_PIECE = + FieldOptions_CType_STRING_PIECE; static inline bool CType_IsValid(int value) { return FieldOptions_CType_IsValid(value); } @@ -2313,9 +2340,12 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { } typedef FieldOptions_JSType JSType; - static const JSType JS_NORMAL = FieldOptions_JSType_JS_NORMAL; - static const JSType JS_STRING = FieldOptions_JSType_JS_STRING; - static const JSType JS_NUMBER = FieldOptions_JSType_JS_NUMBER; + static const JSType JS_NORMAL = + FieldOptions_JSType_JS_NORMAL; + static const JSType JS_STRING = + FieldOptions_JSType_JS_STRING; + static const JSType JS_NUMBER = + FieldOptions_JSType_JS_NUMBER; static inline bool JSType_IsValid(int value) { return FieldOptions_JSType_IsValid(value); } @@ -3686,6 +3716,7 @@ inline ::std::string* FileDescriptorProto::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -3739,6 +3770,7 @@ inline ::std::string* FileDescriptorProto::mutable_package() { return package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -3781,6 +3813,7 @@ inline void FileDescriptorProto::set_dependency(int index, const char* value, si // @@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) return dependency_.Add(); } inline void FileDescriptorProto::add_dependency(const ::std::string& value) { @@ -4013,6 +4046,7 @@ inline ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() { return options_; } inline ::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; @@ -4056,6 +4090,7 @@ inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_c return source_code_info_; } inline ::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; @@ -4112,6 +4147,7 @@ inline ::std::string* FileDescriptorProto::mutable_syntax() { return syntax_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -4273,6 +4309,7 @@ inline ::std::string* DescriptorProto::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -4493,6 +4530,7 @@ inline ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() { return options_; } inline ::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; @@ -4568,6 +4606,7 @@ inline void DescriptorProto::set_reserved_name(int index, const char* value, siz // @@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) return reserved_name_.Add(); } inline void DescriptorProto::add_reserved_name(const ::std::string& value) { @@ -4637,6 +4676,7 @@ inline ::std::string* FieldDescriptorProto::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -4764,6 +4804,7 @@ inline ::std::string* FieldDescriptorProto::mutable_type_name() { return type_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -4817,6 +4858,7 @@ inline ::std::string* FieldDescriptorProto::mutable_extendee() { return extendee_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -4870,6 +4912,7 @@ inline ::std::string* FieldDescriptorProto::mutable_default_value() { return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -4947,6 +4990,7 @@ inline ::std::string* FieldDescriptorProto::mutable_json_name() { return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -4987,6 +5031,7 @@ inline ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() return options_; } inline ::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; @@ -5047,6 +5092,7 @@ inline ::std::string* OneofDescriptorProto::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -5104,6 +5150,7 @@ inline ::std::string* EnumDescriptorProto::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -5174,6 +5221,7 @@ inline ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() { return options_; } 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; @@ -5234,6 +5282,7 @@ inline ::std::string* EnumValueDescriptorProto::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -5298,6 +5347,7 @@ inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_o return options_; } inline ::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; @@ -5358,6 +5408,7 @@ inline ::std::string* ServiceDescriptorProto::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -5428,6 +5479,7 @@ inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_optio return options_; } inline ::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; @@ -5488,6 +5540,7 @@ inline ::std::string* MethodDescriptorProto::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -5541,6 +5594,7 @@ inline ::std::string* MethodDescriptorProto::mutable_input_type() { return input_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -5594,6 +5648,7 @@ inline ::std::string* MethodDescriptorProto::mutable_output_type() { return output_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -5634,6 +5689,7 @@ inline ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options return options_; } inline ::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; @@ -5742,6 +5798,7 @@ inline ::std::string* FileOptions::mutable_java_package() { return java_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -5795,6 +5852,7 @@ inline ::std::string* FileOptions::mutable_java_outer_classname() { return java_outer_classname_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -5945,6 +6003,7 @@ inline ::std::string* FileOptions::mutable_go_package() { return go_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -6118,6 +6177,7 @@ inline ::std::string* FileOptions::mutable_objc_class_prefix() { return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -6171,6 +6231,7 @@ inline ::std::string* FileOptions::mutable_csharp_namespace() { return csharp_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -6824,6 +6885,7 @@ inline ::std::string* UninterpretedOption_NamePart::mutable_name_part() { return name_part_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -6935,6 +6997,7 @@ inline ::std::string* UninterpretedOption::mutable_identifier_value() { return identifier_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -7060,6 +7123,7 @@ inline ::std::string* UninterpretedOption::mutable_string_value() { return string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -7113,6 +7177,7 @@ inline ::std::string* UninterpretedOption::mutable_aggregate_value() { return aggregate_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -7230,6 +7295,7 @@ inline ::std::string* SourceCodeInfo_Location::mutable_leading_comments() { return leading_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -7283,6 +7349,7 @@ inline ::std::string* SourceCodeInfo_Location::mutable_trailing_comments() { return trailing_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } @@ -7325,6 +7392,7 @@ inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, co // @@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) return leading_detached_comments_.Add(); } inline void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) { @@ -7458,6 +7526,7 @@ inline ::std::string* GeneratedCodeInfo_Annotation::mutable_source_file() { return source_file_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index e4720a7e..f937b9ea 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -5740,18 +5740,6 @@ TEST_F(ValidationErrorTest, ValidateProto3Enum) { "}"); } -TEST_F(ValidationErrorTest, ValidateProto3LiteRuntime) { - // Lite runtime is not supported in proto3. - BuildFileWithErrors( - "name: 'foo.proto' " - "syntax: 'proto3' " - "options { " - " optimize_for: LITE_RUNTIME " - "} ", - "foo.proto: foo.proto: OTHER: Lite runtime is not supported " - "in proto3.\n"); -} - TEST_F(ValidationErrorTest, ValidateProto3Group) { BuildFileWithErrors( "name: 'foo.proto' " diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc index c71ce663..e3639346 100644 --- a/src/google/protobuf/duration.pb.cc +++ b/src/google/protobuf/duration.pb.cc @@ -179,8 +179,17 @@ Duration* Duration::New(::google::protobuf::Arena* arena) const { } void Duration::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Duration) +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(Duration, f) \ + _Pragma("clang diagnostic pop") +#else #define ZR_HELPER_(f) reinterpret_cast<char*>(\ &reinterpret_cast<Duration*>(16)->f) +#endif #define ZR_(first, last) do {\ ::memset(&first, 0,\ @@ -196,7 +205,7 @@ void Duration::Clear() { bool Duration::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.Duration) for (;;) { @@ -288,6 +297,7 @@ void Duration::SerializeWithCachedSizes( } int Duration::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Duration) int total_size = 0; // optional int64 seconds = 1; @@ -311,18 +321,22 @@ int Duration::ByteSize() const { } void Duration::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Duration) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const Duration* source = ::google::protobuf::internal::DynamicCastToGenerated<const Duration>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Duration) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Duration) MergeFrom(*source); } } void Duration::MergeFrom(const Duration& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Duration) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from.seconds() != 0) { set_seconds(from.seconds()); @@ -333,12 +347,14 @@ void Duration::MergeFrom(const Duration& from) { } void Duration::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Duration) if (&from == this) return; Clear(); MergeFrom(from); } void Duration::CopyFrom(const Duration& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Duration) if (&from == this) return; Clear(); MergeFrom(from); diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc index 4550921b..dcf84263 100644 --- a/src/google/protobuf/empty.pb.cc +++ b/src/google/protobuf/empty.pb.cc @@ -186,11 +186,12 @@ Empty* Empty::New(::google::protobuf::Arena* arena) const { } void Empty::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Empty) } bool Empty::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.Empty) for (;;) { @@ -228,6 +229,7 @@ void Empty::SerializeWithCachedSizes( } int Empty::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Empty) int total_size = 0; GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); @@ -237,28 +239,34 @@ int Empty::ByteSize() const { } void Empty::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Empty) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const Empty* source = ::google::protobuf::internal::DynamicCastToGenerated<const Empty>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Empty) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Empty) MergeFrom(*source); } } void Empty::MergeFrom(const Empty& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Empty) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); } void Empty::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Empty) if (&from == this) return; Clear(); MergeFrom(from); } void Empty::CopyFrom(const Empty& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Empty) if (&from == this) return; Clear(); MergeFrom(from); diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc index 01a6ce56..c49ebceb 100644 --- a/src/google/protobuf/field_mask.pb.cc +++ b/src/google/protobuf/field_mask.pb.cc @@ -175,12 +175,13 @@ FieldMask* FieldMask::New(::google::protobuf::Arena* arena) const { } void FieldMask::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.FieldMask) paths_.Clear(); } bool FieldMask::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.FieldMask) for (;;) { @@ -262,6 +263,7 @@ void FieldMask::SerializeWithCachedSizes( } int FieldMask::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldMask) int total_size = 0; // repeated string paths = 1; @@ -278,29 +280,35 @@ int FieldMask::ByteSize() const { } void FieldMask::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldMask) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const FieldMask* source = ::google::protobuf::internal::DynamicCastToGenerated<const FieldMask>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FieldMask) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FieldMask) MergeFrom(*source); } } void FieldMask::MergeFrom(const FieldMask& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldMask) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); paths_.MergeFrom(from.paths_); } void FieldMask::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FieldMask) if (&from == this) return; Clear(); MergeFrom(from); } void FieldMask::CopyFrom(const FieldMask& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FieldMask) if (&from == this) return; Clear(); MergeFrom(from); @@ -361,6 +369,7 @@ void FieldMask::clear_paths() { // @@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) { diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h index 7189fd79..f5e0b655 100644 --- a/src/google/protobuf/field_mask.pb.h +++ b/src/google/protobuf/field_mask.pb.h @@ -164,6 +164,7 @@ inline void FieldMask::set_paths(int index, const char* value, size_t 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) return paths_.Add(); } inline void FieldMask::add_paths(const ::std::string& value) { diff --git a/src/google/protobuf/field_mask.proto b/src/google/protobuf/field_mask.proto index b1657f5f..6af6dbe8 100644 --- a/src/google/protobuf/field_mask.proto +++ b/src/google/protobuf/field_mask.proto @@ -88,7 +88,7 @@ option java_generate_equals_and_hash = true; // operation applies to all fields (as if a FieldMask of all fields // had been specified). // -// Note that a field mask does not necessarily applies to the +// 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 diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index eee024ee..2313181c 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -412,6 +412,15 @@ void GeneratedMessageReflection::SwapField( #undef SWAP_ARRAYS case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + MutableRaw<RepeatedPtrFieldBase>(message1, field)-> + Swap<GenericTypeHandler<string> >( + MutableRaw<RepeatedPtrFieldBase>(message2, field)); + break; + } + break; case FieldDescriptor::CPPTYPE_MESSAGE: if (IsMapFieldInApi(field)) { MutableRaw<MapFieldBase>(message1, field)-> @@ -447,16 +456,50 @@ void GeneratedMessageReflection::SwapField( SWAP_VALUES(ENUM , int ); #undef SWAP_VALUES case FieldDescriptor::CPPTYPE_MESSAGE: - std::swap(*MutableRaw<Message*>(message1, field), - *MutableRaw<Message*>(message2, field)); + if (GetArena(message1) == GetArena(message2)) { + std::swap(*MutableRaw<Message*>(message1, field), + *MutableRaw<Message*>(message2, field)); + } else { + Message** sub_msg1 = MutableRaw<Message*>(message1, field); + Message** sub_msg2 = MutableRaw<Message*>(message2, field); + if (*sub_msg1 == NULL && *sub_msg2 == NULL) break; + if (*sub_msg1 && *sub_msg2) { + (*sub_msg1)->GetReflection()->Swap(*sub_msg1, *sub_msg2); + break; + } + if (*sub_msg1 == NULL) { + *sub_msg1 = (*sub_msg2)->New(message1->GetArena()); + (*sub_msg1)->CopyFrom(**sub_msg2); + ClearField(message2, field); + } else { + *sub_msg2 = (*sub_msg1)->New(message2->GetArena()); + (*sub_msg2)->CopyFrom(**sub_msg1); + ClearField(message1, field); + } + } break; case FieldDescriptor::CPPTYPE_STRING: switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: - MutableRaw<ArenaStringPtr>(message1, field)->Swap( - MutableRaw<ArenaStringPtr>(message2, field)); + { + Arena* arena1 = GetArena(message1); + Arena* arena2 = GetArena(message2); + ArenaStringPtr* string1 = + MutableRaw<ArenaStringPtr>(message1, field); + ArenaStringPtr* string2 = + MutableRaw<ArenaStringPtr>(message2, field); + if (arena1 == arena2) { + string1->Swap(string2); + } else { + const string* default_ptr = + &DefaultRaw<ArenaStringPtr>(field).Get(NULL); + const string temp = string1->Get(default_ptr); + string1->Set(default_ptr, string2->Get(default_ptr), arena1); + string2->Set(default_ptr, temp, arena2); + } + } break; } break; @@ -1752,7 +1795,8 @@ bool GeneratedMessageReflection::InsertOrLookupMapValue( "InsertOrLookupMapValue", "Field is not a map field."); val->SetType(field->message_type()->FindFieldByName("value")->cpp_type()); - return MutableRaw<MapFieldBase>(message, field)->InsertMapValue(key, val); + return MutableRaw<MapFieldBase>(message, field)->InsertOrLookupMapValue( + key, val); } bool GeneratedMessageReflection::DeleteMapValue( diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h index 9ef78710..15fc802c 100644 --- a/src/google/protobuf/generated_message_reflection.h +++ b/src/google/protobuf/generated_message_reflection.h @@ -582,7 +582,16 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { // 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 @@ -592,6 +601,7 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { reinterpret_cast<const char*>( \ &reinterpret_cast<const TYPE*>(16)->FIELD) - \ reinterpret_cast<const char*>(16)) +#endif #define PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(ONEOF, FIELD) \ static_cast<int>( \ diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h index 78c8d7ff..4475556a 100644 --- a/src/google/protobuf/generated_message_util.h +++ b/src/google/protobuf/generated_message_util.h @@ -42,8 +42,8 @@ #include <string> #include <google/protobuf/stubs/once.h> - #include <google/protobuf/stubs/common.h> + namespace google { namespace protobuf { @@ -63,6 +63,8 @@ namespace internal { #undef DEPRECATED_PROTOBUF_FIELD #define PROTOBUF_DEPRECATED +#define PROTOBUF_DEPRECATED_ATTR + // Constants for special floating point values. LIBPROTOBUF_EXPORT double Infinity(); diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc index f10d4670..a8108e45 100644 --- a/src/google/protobuf/io/coded_stream_unittest.cc +++ b/src/google/protobuf/io/coded_stream_unittest.cc @@ -47,7 +47,6 @@ #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/scoped_ptr.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> #include <google/protobuf/io/zero_copy_stream_impl.h> 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 cc7430ec..9d81ccfb 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h @@ -175,7 +175,7 @@ class LIBPROTOBUF_EXPORT LazyStringOutputStream : public StringOutputStream { int64 ByteCount() const; private: - const scoped_ptr<ResultCallback<string*> > callback_; + const google::protobuf::scoped_ptr<ResultCallback<string*> > callback_; bool string_is_set_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LazyStringOutputStream); diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc index 8c7358c1..a9db8872 100644 --- a/src/google/protobuf/io/zero_copy_stream_unittest.cc +++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc @@ -63,8 +63,9 @@ #endif #include <sstream> -#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/testing/file.h> #include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> #if HAVE_ZLIB #include <google/protobuf/io/gzip_stream.h> @@ -72,7 +73,6 @@ #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/scoped_ptr.h> #include <google/protobuf/testing/googletest.h> #include <google/protobuf/testing/file.h> #include <gtest/gtest.h> diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index 023ed971..bb0b14f9 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -614,11 +614,12 @@ class Map { !defined(GOOGLE_PROTOBUF_OS_EMSCRIPTEN) template<class NodeType, class... Args> 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<void*>(static_cast<const void*>(p))) NodeType(std::forward<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<void*>(static_cast<const void*>(p))) + NodeType(std::forward<Args>(args)...); } template<class NodeType> @@ -804,6 +805,8 @@ class Map { // Advance through buckets, looking for the first that isn't empty. // If nothing non-empty is found then leave node_ == NULL. 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; for (bucket_index_ = start_bucket; bucket_index_ < m_->num_buckets_; bucket_index_++) { @@ -989,7 +992,7 @@ class Map { void erase(iterator it) { GOOGLE_DCHECK_EQ(it.m_, this); const bool is_list = it.revalidate_if_necessary(); - const size_type b = it.bucket_index_; + size_type b = it.bucket_index_; Node* const item = it.node_; if (is_list) { GOOGLE_DCHECK(TableEntryIsNonEmptyList(b)); @@ -1001,15 +1004,18 @@ class Map { Tree* tree = static_cast<Tree*>(table_[b]); tree->erase(it.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<size_type>(1); DestroyTree(tree); - table_[b] = table_[b ^ 1] = NULL; + table_[b] = table_[b + 1] = NULL; } } DestroyNode(item); --num_elements_; if (GOOGLE_PREDICT_FALSE(b == index_of_first_non_null_)) { while (index_of_first_non_null_ < num_buckets_ && - table_[index_of_first_non_null_] == 0) { + table_[index_of_first_non_null_] == NULL) { ++index_of_first_non_null_; } } @@ -1045,6 +1051,8 @@ class Map { // Requires count(*KeyPtrFromNodePtr(node)) == 0 and that b is the correct // 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); // 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; @@ -1057,11 +1065,16 @@ class Map { if (GOOGLE_PREDICT_FALSE(TableEntryIsTooLong(b))) { TreeConvert(b); result = InsertUniqueInTree(b, node); + GOOGLE_DCHECK_EQ(result.bucket_index_, b & ~static_cast<size_type>(1)); } else { - result = InsertUniqueInList(b, node); + // Insert into a pre-existing list. This case cannot modify + // index_of_first_non_null_, so we skip the code to update it. + return InsertUniqueInList(b, node); } } else { - result = InsertUniqueInTree(b, node); + // Insert into a pre-existing tree. This case cannot modify + // index_of_first_non_null_, so we skip the code to update it. + return InsertUniqueInTree(b, node); } index_of_first_non_null_ = std::min(index_of_first_non_null_, result.bucket_index_); @@ -1137,7 +1150,7 @@ class Map { num_buckets_ = new_num_buckets; table_ = CreateEmptyTable(num_buckets_); const size_type start = index_of_first_non_null_; - index_of_first_non_null_ = 0; + index_of_first_non_null_ = num_buckets_; for (size_type i = start; i < old_table_size; i++) { if (TableEntryIsNonEmptyList(old_table, i)) { TransferList(old_table, i); @@ -1189,10 +1202,10 @@ class Map { return TableEntryIsList(table_, b); } static bool TableEntryIsEmpty(void* const* table, size_type b) { - return table[b] == 0; + return table[b] == NULL; } static bool TableEntryIsNonEmptyList(void* const* table, size_type b) { - return table[b] != 0 && table[b] != table[b ^ 1]; + return table[b] != NULL && table[b] != table[b ^ 1]; } static bool TableEntryIsTree(void* const* table, size_type b) { return !TableEntryIsEmpty(table, b) && @@ -1250,7 +1263,7 @@ class Map { size_type BucketNumber(const Key& k) const { // We inherit from hasher, so one-arg operator() provides a hash function. - size_type h = (*this)(k); + size_type h = (*const_cast<InnerMap*>(this))(k); // To help prevent people from making assumptions about the hash function, // we use the seed differently depending on NDEBUG. The default hash // function, the seeding, etc., are all likely to change in the future. diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc index eddc95c4..49f91818 100644 --- a/src/google/protobuf/map_field.cc +++ b/src/google/protobuf/map_field.cc @@ -178,18 +178,19 @@ bool DynamicMapField::ContainsMapKey( return iter != map.end(); } -bool DynamicMapField::InsertMapValue( +bool DynamicMapField::InsertOrLookupMapValue( const MapKey& map_key, MapValueRef* val) { - bool result = false; - - MapValueRef& map_val = (*MutableMap())[map_key]; - // If map_val.data_ is not set, it is newly inserted by map_[map_key]. - if (map_val.data_ == NULL) { - result = true; + // Always use mutable map because users may change the map value by + // MapValueRef. + Map<MapKey, MapValueRef>* map = MutableMap(); + Map<MapKey, MapValueRef>::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 momery for the inserted MapValueRef, and initialize to + // Allocate memory for the inserted MapValueRef, and initialize to // default value. switch (val_des->cpp_type()) { #define HANDLE_TYPE(CPPTYPE, TYPE) \ @@ -216,9 +217,13 @@ bool DynamicMapField::InsertMapValue( break; } } + val->CopyFrom(map_val); + return true; } - val->CopyFrom(map_val); - return result; + // map_key is already in the map. Make sure (*map)[map_key] is not called. + // [] may reorder the map and iterators. + val->CopyFrom(iter->second); + return false; } bool DynamicMapField::DeleteMapValue(const MapKey& map_key) { diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h index 9130166b..4b46f3aa 100644 --- a/src/google/protobuf/map_field.h +++ b/src/google/protobuf/map_field.h @@ -87,7 +87,8 @@ class LIBPROTOBUF_EXPORT MapFieldBase { // Pure virtual map APIs for Map Reflection. virtual bool ContainsMapKey(const MapKey& map_key) const = 0; - virtual bool InsertMapValue(const MapKey& map_key, MapValueRef* val) = 0; + virtual bool InsertOrLookupMapValue( + const MapKey& map_key, MapValueRef* val) = 0; virtual bool DeleteMapValue(const MapKey& map_key) = 0; virtual bool EqualIterator(const MapIterator& a, const MapIterator& b) const = 0; @@ -251,7 +252,7 @@ class MapField : public TypeDefinedMapFieldBase<Key, T>, // Implement MapFieldBase bool ContainsMapKey(const MapKey& map_key) const; - bool InsertMapValue(const MapKey& map_key, MapValueRef* val); + bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val); bool DeleteMapValue(const MapKey& map_key); // Accessors @@ -302,7 +303,7 @@ class LIBPROTOBUF_EXPORT DynamicMapField: public TypeDefinedMapFieldBase<MapKey, // Implement MapFieldBase bool ContainsMapKey(const MapKey& map_key) const; - bool InsertMapValue(const MapKey& map_key, MapValueRef* val); + bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val); bool DeleteMapValue(const MapKey& map_key); const Map<MapKey, MapValueRef>& GetMap() const; diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h index f116697c..01c9b89a 100644 --- a/src/google/protobuf/map_field_inl.h +++ b/src/google/protobuf/map_field_inl.h @@ -262,16 +262,22 @@ template <typename Key, typename T, WireFormatLite::FieldType kValueFieldType, int default_enum_value> bool MapField<Key, T, kKeyFieldType, kValueFieldType, - default_enum_value>::InsertMapValue(const MapKey& map_key, - MapValueRef* val) { + default_enum_value>::InsertOrLookupMapValue( + const MapKey& map_key, + MapValueRef* val) { + // Always use mutable map because users may change the map value by + // MapValueRef. Map<Key, T>* map = MutableMap(); - bool result = false; const Key& key = UnwrapMapKey<Key>(map_key); - if (map->end() == map->find(key)) { - result = true; + typename Map<Key, T>::iterator iter = map->find(key); + if (map->end() == iter) { + val->SetValue(&((*map)[key])); + return true; } - val->SetValue(&((*map)[key])); - return result; + // Key is already in the map. Make sure (*map)[key] is not called. + // [] may reorder the map and iterators. + val->SetValue(&(iter->second)); + return false; } template <typename Key, typename T, diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc index 2ff1d6bb..223d42f3 100644 --- a/src/google/protobuf/map_field_test.cc +++ b/src/google/protobuf/map_field_test.cc @@ -78,7 +78,7 @@ class MapFieldBaseStub : public MapFieldBase { bool ContainsMapKey(const MapKey& map_key) const { return false; } - bool InsertMapValue(const MapKey& map_key, MapValueRef* val) { + bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) { return false; } bool DeleteMapValue(const MapKey& map_key) { diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc index e833699a..9d4d6c13 100644 --- a/src/google/protobuf/map_test.cc +++ b/src/google/protobuf/map_test.cc @@ -307,6 +307,11 @@ static int64 Now() { google::protobuf::util::TimeUtil::GetCurrentTime()); } +// Arbitrary odd integers for creating test data. +static int k0 = 812398771; +static int k1 = 1312938717; +static int k2 = 1321555333; + // A naive begin() implementation will cause begin() to get slower and slower // if one erases elements at the "front" of the hash map, and we'd like to // avoid that, as std::unordered_map does. @@ -315,8 +320,18 @@ TEST_P(MapImplTest, BeginIsFast) { if (/*GetParam()*/true) return; Map<int32, int32> map(false); // This test uses new-style maps only. const int kTestSize = 250000; - for (int i = 0; i < kTestSize; i++) { - map[i] = i; + // Create a random-looking map of size n. Use non-negative integer keys. + uint32 frog = 123983; + int last_key = 0; + int counter = 0; + while (map.size() < kTestSize) { + frog *= static_cast<uint32>(k0); + frog ^= frog >> 17; + frog += counter++; + last_key = + static_cast<int>(frog) >= 0 ? static_cast<int>(frog) : last_key ^ 1; + GOOGLE_DCHECK_GE(last_key, 0); + map[last_key] = last_key ^ 1; } vector<int64> times; // We're going to do map.erase(map.begin()) over and over again. But, @@ -384,11 +399,6 @@ TEST_P(MapImplTest, HashFlood) { EXPECT_LE(x1, x0 * 20); } -// Arbitrary odd integers for creating test data. -static int k0 = 812398771; -static int k1 = 1312938717; -static int k2 = 1321555333; - template <typename T, typename U> static void TestValidityForAllKeysExcept(int key_to_avoid, const T& check_map, diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index fe124c45..9d7b64f7 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc @@ -361,6 +361,11 @@ void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from, MessageLite* to) { to->CheckTypeAndMergeFrom(from); } +template<> +void GenericTypeHandler<string>::Merge(const string& from, + string* to) { + *to = from; +} } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/proto3_arena_lite_unittest.cc b/src/google/protobuf/proto3_arena_lite_unittest.cc new file mode 100644 index 00000000..0f18c027 --- /dev/null +++ b/src/google/protobuf/proto3_arena_lite_unittest.cc @@ -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. + +#include <string> +#include <memory> +#ifndef _SHARED_PTR_H +#include <google/protobuf/stubs/shared_ptr.h> +#endif +#include <vector> + +#include <google/protobuf/test_util.h> +#include <google/protobuf/unittest.pb.h> +#include <google/protobuf/unittest_proto3_arena_lite.pb.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/testing/googletest.h> +#include <gtest/gtest.h> + +namespace google { +using proto3_arena_lite_unittest::TestAllTypes; + +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 arena 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_arena_lite_unittest::TestAllTypes_NestedEnum_BAZ); + m->set_optional_foreign_enum( + proto3_arena_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_arena_lite_unittest::TestAllTypes_NestedEnum_BAZ); + m->add_repeated_foreign_enum( + proto3_arena_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_arena_lite_unittest::TestAllTypes_NestedEnum_BAZ, + m.optional_nested_enum()); + EXPECT_EQ(proto3_arena_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_arena_lite_unittest::TestAllTypes_NestedEnum_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(1, m.repeated_lazy_message_size()); + EXPECT_EQ(49, m.repeated_lazy_message(0).bb()); + + EXPECT_EQ(proto3_arena_lite_unittest::TestAllTypes::kOneofString, + m.oneof_field_case()); + EXPECT_EQ("test", m.oneof_string()); +} + +// In this file we only test some basic functionalities of arena support in +// proto3 and expect the arena support to be fully tested in proto2 unittests +// because proto3 shares most code with proto2. + +TEST(Proto3ArenaLiteTest, Parsing) { + TestAllTypes original; + SetAllFields(&original); + + Arena arena; + TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena); + arena_message->ParseFromString(original.SerializeAsString()); + ExpectAllFieldsSet(*arena_message); +} + +TEST(Proto3ArenaLiteTest, Swap) { + Arena arena1; + Arena arena2; + + // Test Swap(). + TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1); + TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2); + arena1_message->Swap(arena2_message); + EXPECT_EQ(&arena1, arena1_message->GetArena()); + EXPECT_EQ(&arena2, arena2_message->GetArena()); +} + +TEST(Proto3ArenaLiteTest, SetAllocatedMessage) { + Arena arena; + TestAllTypes *arena_message = Arena::CreateMessage<TestAllTypes>(&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()); +} + +TEST(Proto3ArenaLiteTest, ReleaseMessage) { + Arena arena; + TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena); + arena_message->mutable_optional_nested_message()->set_bb(118); + google::protobuf::scoped_ptr<TestAllTypes::NestedMessage> nested( + arena_message->release_optional_nested_message()); + EXPECT_EQ(118, nested->bb()); +} + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/proto3_lite_unittest.cc b/src/google/protobuf/proto3_lite_unittest.cc new file mode 100644 index 00000000..2e2beea9 --- /dev/null +++ b/src/google/protobuf/proto3_lite_unittest.cc @@ -0,0 +1,145 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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 <string> +#include <memory> +#ifndef _SHARED_PTR_H +#include <google/protobuf/stubs/shared_ptr.h> +#endif +#include <vector> + +#include <google/protobuf/test_util.h> +#include <google/protobuf/unittest.pb.h> +#include <google/protobuf/unittest_proto3_lite.pb.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/testing/googletest.h> +#include <gtest/gtest.h> + +namespace google { +using proto3_lite_unittest::TestAllTypes; + +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/repeated_field.h b/src/google/protobuf/repeated_field.h index deeb7d50..1961bc48 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -626,6 +626,13 @@ inline void* GenericTypeHandler<MessageLite>::GetMaybeArenaPointer( template <> void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from, MessageLite* to); +template<> +inline void GenericTypeHandler<string>::Clear(string* value) { + value->clear(); +} +template<> +void GenericTypeHandler<string>::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. diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc index f2eb7ae7..c67cd102 100644 --- a/src/google/protobuf/source_context.pb.cc +++ b/src/google/protobuf/source_context.pb.cc @@ -177,12 +177,13 @@ SourceContext* SourceContext::New(::google::protobuf::Arena* arena) const { } void SourceContext::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.SourceContext) file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } bool SourceContext::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.SourceContext) for (;;) { @@ -262,6 +263,7 @@ void SourceContext::SerializeWithCachedSizes( } int SourceContext::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceContext) int total_size = 0; // optional string file_name = 1; @@ -278,18 +280,22 @@ int SourceContext::ByteSize() const { } void SourceContext::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceContext) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const SourceContext* source = ::google::protobuf::internal::DynamicCastToGenerated<const SourceContext>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.SourceContext) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.SourceContext) MergeFrom(*source); } } void SourceContext::MergeFrom(const SourceContext& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceContext) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from.file_name().size() > 0) { @@ -298,12 +304,14 @@ void SourceContext::MergeFrom(const SourceContext& from) { } void SourceContext::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.SourceContext) if (&from == this) return; Clear(); MergeFrom(from); } void SourceContext::CopyFrom(const SourceContext& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.SourceContext) if (&from == this) return; Clear(); MergeFrom(from); @@ -365,6 +373,7 @@ void SourceContext::clear_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()); } diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h index 02e11460..ccfd365b 100644 --- a/src/google/protobuf/source_context.pb.h +++ b/src/google/protobuf/source_context.pb.h @@ -160,6 +160,7 @@ inline ::std::string* SourceContext::mutable_file_name() { return file_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } 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()); } diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc index 9e5b086b..11ccabbf 100644 --- a/src/google/protobuf/struct.pb.cc +++ b/src/google/protobuf/struct.pb.cc @@ -282,12 +282,13 @@ Struct* Struct::New(::google::protobuf::Arena* arena) const { } void Struct::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Struct) fields_.Clear(); } bool Struct::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.Struct) for (;;) { @@ -385,6 +386,7 @@ void Struct::SerializeWithCachedSizes( } int Struct::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Struct) int total_size = 0; // map<string, .google.protobuf.Value> fields = 1; @@ -407,29 +409,35 @@ int Struct::ByteSize() const { } void Struct::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Struct) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const Struct* source = ::google::protobuf::internal::DynamicCastToGenerated<const Struct>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Struct) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Struct) MergeFrom(*source); } } void Struct::MergeFrom(const Struct& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Struct) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); fields_.MergeFrom(from.fields_); } void Struct::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Struct) if (&from == this) return; Clear(); MergeFrom(from); } void Struct::CopyFrom(const Struct& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Struct) if (&from == this) return; Clear(); MergeFrom(from); @@ -562,6 +570,7 @@ Value* Value::New(::google::protobuf::Arena* arena) const { } void Value::clear_kind() { +// @@protoc_insertion_point(one_of_clear_start:google.protobuf.Value) switch(kind_case()) { case kNullValue: { // No need to clear @@ -596,12 +605,13 @@ void Value::clear_kind() { void Value::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Value) clear_kind(); } bool Value::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.Value) for (;;) { @@ -813,6 +823,7 @@ void Value::SerializeWithCachedSizes( } int Value::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Value) int total_size = 0; switch (kind_case()) { @@ -864,18 +875,22 @@ int Value::ByteSize() const { } void Value::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Value) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const Value* source = ::google::protobuf::internal::DynamicCastToGenerated<const Value>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Value) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Value) MergeFrom(*source); } } void Value::MergeFrom(const Value& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Value) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); switch (from.kind_case()) { case kNullValue: { @@ -909,12 +924,14 @@ void Value::MergeFrom(const Value& from) { } void Value::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Value) if (&from == this) return; Clear(); MergeFrom(from); } void Value::CopyFrom(const Value& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Value) if (&from == this) return; Clear(); MergeFrom(from); @@ -1065,6 +1082,7 @@ void Value::clear_string_value() { return kind_.string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } ::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_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); @@ -1143,6 +1161,7 @@ void Value::clear_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(); ::google::protobuf::Struct* temp = kind_.struct_value_; @@ -1190,6 +1209,7 @@ void Value::clear_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(); ::google::protobuf::ListValue* temp = kind_.list_value_; @@ -1284,12 +1304,13 @@ ListValue* ListValue::New(::google::protobuf::Arena* arena) const { } void ListValue::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.ListValue) values_.Clear(); } bool ListValue::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.ListValue) for (;;) { @@ -1361,6 +1382,7 @@ void ListValue::SerializeWithCachedSizes( } int ListValue::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ListValue) int total_size = 0; // repeated .google.protobuf.Value values = 1; @@ -1378,29 +1400,35 @@ int ListValue::ByteSize() const { } void ListValue::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ListValue) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const ListValue* source = ::google::protobuf::internal::DynamicCastToGenerated<const ListValue>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ListValue) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ListValue) MergeFrom(*source); } } void ListValue::MergeFrom(const ListValue& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ListValue) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); values_.MergeFrom(from.values_); } void ListValue::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ListValue) if (&from == this) return; Clear(); MergeFrom(from); } void ListValue::CopyFrom(const ListValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.ListValue) if (&from == this) return; Clear(); MergeFrom(from); diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h index 0527c812..6a4764a7 100644 --- a/src/google/protobuf/struct.pb.h +++ b/src/google/protobuf/struct.pb.h @@ -550,6 +550,7 @@ inline ::std::string* Value::mutable_string_value() { return kind_.string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline ::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_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); @@ -628,6 +629,7 @@ inline ::google::protobuf::Struct* Value::mutable_struct_value() { return kind_.struct_value_; } inline ::google::protobuf::Struct* Value::release_struct_value() { + // @@protoc_insertion_point(field_release:google.protobuf.Value.struct_value) if (has_struct_value()) { clear_has_kind(); ::google::protobuf::Struct* temp = kind_.struct_value_; @@ -675,6 +677,7 @@ inline ::google::protobuf::ListValue* Value::mutable_list_value() { return kind_.list_value_; } inline ::google::protobuf::ListValue* Value::release_list_value() { + // @@protoc_insertion_point(field_release:google.protobuf.Value.list_value) if (has_list_value()) { clear_has_kind(); ::google::protobuf::ListValue* temp = kind_.list_value_; diff --git a/src/google/protobuf/stubs/stringprintf.cc b/src/google/protobuf/stubs/stringprintf.cc index 3272d8e3..83fdfe45 100644 --- a/src/google/protobuf/stubs/stringprintf.cc +++ b/src/google/protobuf/stubs/stringprintf.cc @@ -37,7 +37,6 @@ #include <stdio.h> // MSVC requires this for _vsnprintf #include <vector> #include <google/protobuf/stubs/common.h> -#include <google/protobuf/testing/googletest.h> namespace google { namespace protobuf { diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index 1ed74391..c0dfd53f 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -1785,14 +1785,12 @@ void TextFormat::Printer::PrintFieldValue( ? reflection->GetRepeatedStringReference( message, field, index, &scratch) : reflection->GetStringReference(message, field, &scratch); - int64 size = value.size(); - if (truncate_string_field_longer_than_ > 0) { - size = std::min(truncate_string_field_longer_than_, - static_cast<int64>(value.size())); - } - string truncated_value(value.substr(0, size) + "...<truncated>..."); const string* value_to_print = &value; - if (size < value.size()) { + string truncated_value; + if (truncate_string_field_longer_than_ > 0 && + truncate_string_field_longer_than_ < value.size()) { + truncated_value = value.substr(0, truncate_string_field_longer_than_) + + "...<truncated>..."; value_to_print = &truncated_value; } if (field->type() == FieldDescriptor::TYPE_STRING) { diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc index f97658fd..58aa3f8d 100644 --- a/src/google/protobuf/text_format_unittest.cc +++ b/src/google/protobuf/text_format_unittest.cc @@ -46,6 +46,7 @@ #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/logging.h> #include <google/protobuf/testing/file.h> +#include <google/protobuf/testing/file.h> #include <google/protobuf/test_util.h> #include <google/protobuf/unittest.pb.h> #include <google/protobuf/unittest_mset.pb.h> @@ -53,10 +54,10 @@ #include <google/protobuf/io/tokenizer.h> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/mathlimits.h> #include <google/protobuf/stubs/substitute.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> +#include <google/protobuf/stubs/mathlimits.h> namespace google { diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc index 1393cc95..7cdf5093 100644 --- a/src/google/protobuf/timestamp.pb.cc +++ b/src/google/protobuf/timestamp.pb.cc @@ -193,8 +193,17 @@ Timestamp* Timestamp::New(::google::protobuf::Arena* arena) const { } void Timestamp::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Timestamp) +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(Timestamp, f) \ + _Pragma("clang diagnostic pop") +#else #define ZR_HELPER_(f) reinterpret_cast<char*>(\ &reinterpret_cast<Timestamp*>(16)->f) +#endif #define ZR_(first, last) do {\ ::memset(&first, 0,\ @@ -210,7 +219,7 @@ void Timestamp::Clear() { bool Timestamp::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.Timestamp) for (;;) { @@ -302,6 +311,7 @@ void Timestamp::SerializeWithCachedSizes( } int Timestamp::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Timestamp) int total_size = 0; // optional int64 seconds = 1; @@ -325,18 +335,22 @@ int Timestamp::ByteSize() const { } void Timestamp::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Timestamp) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const Timestamp* source = ::google::protobuf::internal::DynamicCastToGenerated<const Timestamp>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Timestamp) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Timestamp) MergeFrom(*source); } } void Timestamp::MergeFrom(const Timestamp& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Timestamp) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from.seconds() != 0) { set_seconds(from.seconds()); @@ -347,12 +361,14 @@ void Timestamp::MergeFrom(const Timestamp& from) { } void Timestamp::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Timestamp) if (&from == this) return; Clear(); MergeFrom(from); } void Timestamp::CopyFrom(const Timestamp& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Timestamp) if (&from == this) return; Clear(); MergeFrom(from); diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc index 7b47b3bd..759cab27 100644 --- a/src/google/protobuf/type.pb.cc +++ b/src/google/protobuf/type.pb.cc @@ -359,6 +359,7 @@ Type* Type::New(::google::protobuf::Arena* arena) const { } void Type::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Type) name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_; source_context_ = NULL; @@ -370,7 +371,7 @@ void Type::Clear() { bool Type::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.Type) for (;;) { @@ -603,6 +604,7 @@ void Type::SerializeWithCachedSizes( } int Type::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Type) int total_size = 0; // optional string name = 1; @@ -655,18 +657,22 @@ int Type::ByteSize() const { } void Type::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Type) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const Type* source = ::google::protobuf::internal::DynamicCastToGenerated<const Type>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Type) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Type) MergeFrom(*source); } } void Type::MergeFrom(const Type& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Type) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); fields_.MergeFrom(from.fields_); oneofs_.MergeFrom(from.oneofs_); @@ -684,12 +690,14 @@ void Type::MergeFrom(const Type& from) { } void Type::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Type) if (&from == this) return; Clear(); MergeFrom(from); } void Type::CopyFrom(const Type& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Type) if (&from == this) return; Clear(); MergeFrom(from); @@ -756,6 +764,7 @@ void Type::clear_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } ::std::string* Type::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Type.name) return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -828,6 +837,7 @@ void Type::clear_oneofs() { // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.oneofs) } ::std::string* Type::add_oneofs() { + // @@protoc_insertion_point(field_add_mutable:google.protobuf.Type.oneofs) return oneofs_.Add(); } void Type::add_oneofs(const ::std::string& value) { @@ -904,6 +914,7 @@ const ::google::protobuf::SourceContext& Type::source_context() const { return source_context_; } ::google::protobuf::SourceContext* Type::release_source_context() { + // @@protoc_insertion_point(field_release:google.protobuf.Type.source_context) ::google::protobuf::SourceContext* temp = source_context_; source_context_ = NULL; @@ -1104,8 +1115,17 @@ Field* Field::New(::google::protobuf::Arena* arena) const { } void Field::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Field) +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(Field, f) \ + _Pragma("clang diagnostic pop") +#else #define ZR_HELPER_(f) reinterpret_cast<char*>(\ &reinterpret_cast<Field*>(16)->f) +#endif #define ZR_(first, last) do {\ ::memset(&first, 0,\ @@ -1128,7 +1148,7 @@ void Field::Clear() { bool Field::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.Field) for (;;) { @@ -1483,6 +1503,7 @@ void Field::SerializeWithCachedSizes( } int Field::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Field) int total_size = 0; // optional .google.protobuf.Field.Kind kind = 1; @@ -1559,18 +1580,22 @@ int Field::ByteSize() const { } void Field::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Field) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const Field* source = ::google::protobuf::internal::DynamicCastToGenerated<const Field>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Field) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Field) MergeFrom(*source); } } void Field::MergeFrom(const Field& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Field) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); options_.MergeFrom(from.options_); if (from.kind() != 0) { @@ -1607,12 +1632,14 @@ void Field::MergeFrom(const Field& from) { } void Field::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Field) if (&from == this) return; Clear(); MergeFrom(from); } void Field::CopyFrom(const Field& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Field) if (&from == this) return; Clear(); MergeFrom(from); @@ -1725,6 +1752,7 @@ void Field::clear_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } ::std::string* Field::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Field.name) return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -1768,6 +1796,7 @@ void Field::clear_type_url() { return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } ::std::string* Field::release_type_url() { + // @@protoc_insertion_point(field_release:google.protobuf.Field.type_url) return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -1869,6 +1898,7 @@ void Field::clear_json_name() { return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } ::std::string* Field::release_json_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Field.json_name) return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -1912,6 +1942,7 @@ void Field::clear_default_value() { return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } ::std::string* Field::release_default_value() { + // @@protoc_insertion_point(field_release:google.protobuf.Field.default_value) return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -2003,6 +2034,7 @@ Enum* Enum::New(::google::protobuf::Arena* arena) const { } void Enum::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Enum) name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_; source_context_ = NULL; @@ -2013,7 +2045,7 @@ void Enum::Clear() { bool Enum::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.Enum) for (;;) { @@ -2206,6 +2238,7 @@ void Enum::SerializeWithCachedSizes( } int Enum::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Enum) int total_size = 0; // optional string name = 1; @@ -2251,18 +2284,22 @@ int Enum::ByteSize() const { } void Enum::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Enum) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const Enum* source = ::google::protobuf::internal::DynamicCastToGenerated<const Enum>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Enum) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Enum) MergeFrom(*source); } } void Enum::MergeFrom(const Enum& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Enum) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); enumvalue_.MergeFrom(from.enumvalue_); options_.MergeFrom(from.options_); @@ -2279,12 +2316,14 @@ void Enum::MergeFrom(const Enum& from) { } void Enum::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Enum) if (&from == this) return; Clear(); MergeFrom(from); } void Enum::CopyFrom(const Enum& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Enum) if (&from == this) return; Clear(); MergeFrom(from); @@ -2350,6 +2389,7 @@ void Enum::clear_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } ::std::string* Enum::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Enum.name) return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -2444,6 +2484,7 @@ const ::google::protobuf::SourceContext& Enum::source_context() const { return source_context_; } ::google::protobuf::SourceContext* Enum::release_source_context() { + // @@protoc_insertion_point(field_release:google.protobuf.Enum.source_context) ::google::protobuf::SourceContext* temp = source_context_; source_context_ = NULL; @@ -2547,6 +2588,7 @@ EnumValue* EnumValue::New(::google::protobuf::Arena* arena) const { } void EnumValue::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValue) name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); number_ = 0; options_.Clear(); @@ -2554,7 +2596,7 @@ void EnumValue::Clear() { bool EnumValue::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.EnumValue) for (;;) { @@ -2689,6 +2731,7 @@ void EnumValue::SerializeWithCachedSizes( } int EnumValue::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValue) int total_size = 0; // optional string name = 1; @@ -2720,18 +2763,22 @@ int EnumValue::ByteSize() const { } void EnumValue::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValue) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const EnumValue* source = ::google::protobuf::internal::DynamicCastToGenerated<const EnumValue>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumValue) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumValue) MergeFrom(*source); } } void EnumValue::MergeFrom(const EnumValue& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValue) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); options_.MergeFrom(from.options_); if (from.name().size() > 0) { @@ -2744,12 +2791,14 @@ void EnumValue::MergeFrom(const EnumValue& from) { } void EnumValue::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumValue) if (&from == this) return; Clear(); MergeFrom(from); } void EnumValue::CopyFrom(const EnumValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumValue) if (&from == this) return; Clear(); MergeFrom(from); @@ -2813,6 +2862,7 @@ void EnumValue::clear_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } ::std::string* EnumValue::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.EnumValue.name) return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -2944,6 +2994,7 @@ Option* Option::New(::google::protobuf::Arena* arena) const { } void Option::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Option) name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_; value_ = NULL; @@ -2951,7 +3002,7 @@ void Option::Clear() { bool Option::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.Option) for (;;) { @@ -3057,6 +3108,7 @@ void Option::SerializeWithCachedSizes( } int Option::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Option) int total_size = 0; // optional string name = 1; @@ -3080,18 +3132,22 @@ int Option::ByteSize() const { } void Option::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Option) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const Option* source = ::google::protobuf::internal::DynamicCastToGenerated<const Option>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Option) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Option) MergeFrom(*source); } } void Option::MergeFrom(const Option& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Option) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from.name().size() > 0) { @@ -3103,12 +3159,14 @@ void Option::MergeFrom(const Option& from) { } void Option::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Option) if (&from == this) return; Clear(); MergeFrom(from); } void Option::CopyFrom(const Option& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Option) if (&from == this) return; Clear(); MergeFrom(from); @@ -3171,6 +3229,7 @@ void Option::clear_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } ::std::string* Option::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Option.name) return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -3205,6 +3264,7 @@ const ::google::protobuf::Any& Option::value() const { return value_; } ::google::protobuf::Any* Option::release_value() { + // @@protoc_insertion_point(field_release:google.protobuf.Option.value) ::google::protobuf::Any* temp = value_; value_ = NULL; diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h index 76fe8a65..4255fa8c 100644 --- a/src/google/protobuf/type.pb.h +++ b/src/google/protobuf/type.pb.h @@ -328,25 +328,44 @@ class LIBPROTOBUF_EXPORT Field : public ::google::protobuf::Message { // nested types ---------------------------------------------------- typedef Field_Kind Kind; - static const Kind TYPE_UNKNOWN = Field_Kind_TYPE_UNKNOWN; - static const Kind TYPE_DOUBLE = Field_Kind_TYPE_DOUBLE; - static const Kind TYPE_FLOAT = Field_Kind_TYPE_FLOAT; - static const Kind TYPE_INT64 = Field_Kind_TYPE_INT64; - static const Kind TYPE_UINT64 = Field_Kind_TYPE_UINT64; - static const Kind TYPE_INT32 = Field_Kind_TYPE_INT32; - static const Kind TYPE_FIXED64 = Field_Kind_TYPE_FIXED64; - static const Kind TYPE_FIXED32 = Field_Kind_TYPE_FIXED32; - static const Kind TYPE_BOOL = Field_Kind_TYPE_BOOL; - static const Kind TYPE_STRING = Field_Kind_TYPE_STRING; - static const Kind TYPE_GROUP = Field_Kind_TYPE_GROUP; - static const Kind TYPE_MESSAGE = Field_Kind_TYPE_MESSAGE; - static const Kind TYPE_BYTES = Field_Kind_TYPE_BYTES; - static const Kind TYPE_UINT32 = Field_Kind_TYPE_UINT32; - static const Kind TYPE_ENUM = Field_Kind_TYPE_ENUM; - static const Kind TYPE_SFIXED32 = Field_Kind_TYPE_SFIXED32; - static const Kind TYPE_SFIXED64 = Field_Kind_TYPE_SFIXED64; - static const Kind TYPE_SINT32 = Field_Kind_TYPE_SINT32; - static const Kind TYPE_SINT64 = Field_Kind_TYPE_SINT64; + static const Kind TYPE_UNKNOWN = + Field_Kind_TYPE_UNKNOWN; + static const Kind TYPE_DOUBLE = + Field_Kind_TYPE_DOUBLE; + static const Kind TYPE_FLOAT = + Field_Kind_TYPE_FLOAT; + static const Kind TYPE_INT64 = + Field_Kind_TYPE_INT64; + static const Kind TYPE_UINT64 = + Field_Kind_TYPE_UINT64; + static const Kind TYPE_INT32 = + Field_Kind_TYPE_INT32; + static const Kind TYPE_FIXED64 = + Field_Kind_TYPE_FIXED64; + static const Kind TYPE_FIXED32 = + Field_Kind_TYPE_FIXED32; + static const Kind TYPE_BOOL = + Field_Kind_TYPE_BOOL; + static const Kind TYPE_STRING = + Field_Kind_TYPE_STRING; + static const Kind TYPE_GROUP = + Field_Kind_TYPE_GROUP; + static const Kind TYPE_MESSAGE = + Field_Kind_TYPE_MESSAGE; + static const Kind TYPE_BYTES = + Field_Kind_TYPE_BYTES; + static const Kind TYPE_UINT32 = + Field_Kind_TYPE_UINT32; + static const Kind TYPE_ENUM = + Field_Kind_TYPE_ENUM; + static const Kind TYPE_SFIXED32 = + Field_Kind_TYPE_SFIXED32; + static const Kind TYPE_SFIXED64 = + Field_Kind_TYPE_SFIXED64; + static const Kind TYPE_SINT32 = + Field_Kind_TYPE_SINT32; + static const Kind TYPE_SINT64 = + Field_Kind_TYPE_SINT64; static inline bool Kind_IsValid(int value) { return Field_Kind_IsValid(value); } @@ -369,10 +388,14 @@ class LIBPROTOBUF_EXPORT Field : public ::google::protobuf::Message { } typedef Field_Cardinality Cardinality; - static const Cardinality CARDINALITY_UNKNOWN = Field_Cardinality_CARDINALITY_UNKNOWN; - static const Cardinality CARDINALITY_OPTIONAL = Field_Cardinality_CARDINALITY_OPTIONAL; - static const Cardinality CARDINALITY_REQUIRED = Field_Cardinality_CARDINALITY_REQUIRED; - static const Cardinality CARDINALITY_REPEATED = Field_Cardinality_CARDINALITY_REPEATED; + static const Cardinality CARDINALITY_UNKNOWN = + Field_Cardinality_CARDINALITY_UNKNOWN; + static const Cardinality CARDINALITY_OPTIONAL = + Field_Cardinality_CARDINALITY_OPTIONAL; + static const Cardinality CARDINALITY_REQUIRED = + Field_Cardinality_CARDINALITY_REQUIRED; + static const Cardinality CARDINALITY_REPEATED = + Field_Cardinality_CARDINALITY_REPEATED; static inline bool Cardinality_IsValid(int value) { return Field_Cardinality_IsValid(value); } @@ -865,6 +888,7 @@ inline ::std::string* Type::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline ::std::string* Type::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Type.name) return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -937,6 +961,7 @@ inline void Type::set_oneofs(int index, const char* value, size_t size) { // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.oneofs) } inline ::std::string* Type::add_oneofs() { + // @@protoc_insertion_point(field_add_mutable:google.protobuf.Type.oneofs) return oneofs_.Add(); } inline void Type::add_oneofs(const ::std::string& value) { @@ -1013,6 +1038,7 @@ inline ::google::protobuf::SourceContext* Type::mutable_source_context() { return source_context_; } inline ::google::protobuf::SourceContext* Type::release_source_context() { + // @@protoc_insertion_point(field_release:google.protobuf.Type.source_context) ::google::protobuf::SourceContext* temp = source_context_; source_context_ = NULL; @@ -1119,6 +1145,7 @@ inline ::std::string* Field::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline ::std::string* Field::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Field.name) return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -1162,6 +1189,7 @@ inline ::std::string* Field::mutable_type_url() { return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline ::std::string* Field::release_type_url() { + // @@protoc_insertion_point(field_release:google.protobuf.Field.type_url) return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -1263,6 +1291,7 @@ inline ::std::string* Field::mutable_json_name() { return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline ::std::string* Field::release_json_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Field.json_name) return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -1306,6 +1335,7 @@ inline ::std::string* Field::mutable_default_value() { return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline ::std::string* Field::release_default_value() { + // @@protoc_insertion_point(field_release:google.protobuf.Field.default_value) return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -1353,6 +1383,7 @@ inline ::std::string* Enum::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline ::std::string* Enum::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Enum.name) return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -1447,6 +1478,7 @@ inline ::google::protobuf::SourceContext* Enum::mutable_source_context() { return source_context_; } inline ::google::protobuf::SourceContext* Enum::release_source_context() { + // @@protoc_insertion_point(field_release:google.protobuf.Enum.source_context) ::google::protobuf::SourceContext* temp = source_context_; source_context_ = NULL; @@ -1511,6 +1543,7 @@ inline ::std::string* EnumValue::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline ::std::string* EnumValue::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.EnumValue.name) return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -1602,6 +1635,7 @@ inline ::std::string* Option::mutable_name() { return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline ::std::string* Option::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Option.name) return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -1636,6 +1670,7 @@ inline ::google::protobuf::Any* Option::mutable_value() { return value_; } inline ::google::protobuf::Any* Option::release_value() { + // @@protoc_insertion_point(field_release:google.protobuf.Option.value) ::google::protobuf::Any* temp = value_; value_ = NULL; diff --git a/src/google/protobuf/unittest_proto3_arena_lite.proto b/src/google/protobuf/unittest_proto3_arena_lite.proto new file mode 100644 index 00000000..5a60b90f --- /dev/null +++ b/src/google/protobuf/unittest_proto3_arena_lite.proto @@ -0,0 +1,207 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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"; + +option cc_enable_arenas = true; +option optimize_for = LITE_RUNTIME; + +import "google/protobuf/unittest_import.proto"; + +package proto3_arena_lite_unittest; + +// This proto includes every type of field in both singular and repeated +// forms. +message TestAllTypes { + message NestedMessage { + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + + enum NestedEnum { + ZERO = 0; + FOO = 1; + BAR = 2; + BAZ = 3; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + sint32 optional_sint32 = 5; + sint64 optional_sint64 = 6; + fixed32 optional_fixed32 = 7; + fixed64 optional_fixed64 = 8; + sfixed32 optional_sfixed32 = 9; + sfixed64 optional_sfixed64 = 10; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; + + // Groups are not allowed in proto3. + // optional group OptionalGroup = 16 { + // optional int32 a = 17; + // } + + NestedMessage optional_nested_message = 18; + ForeignMessage optional_foreign_message = 19; + protobuf_unittest_import.ImportMessage optional_import_message = 20; + + NestedEnum optional_nested_enum = 21; + ForeignEnum optional_foreign_enum = 22; + + // Omitted (compared to unittest.proto) because proto2 enums are not allowed + // inside proto2 messages. + // + // optional protobuf_unittest_import.ImportEnum optional_import_enum = 23; + + string optional_string_piece = 24 [ctype=STRING_PIECE]; + string optional_cord = 25 [ctype=CORD]; + + // Defined in unittest_import_public.proto + protobuf_unittest_import.PublicImportMessage + optional_public_import_message = 26; + + 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; + + // Groups are not allowed in proto3. + // repeated group RepeatedGroup = 46 { + // optional int32 a = 47; + // } + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + + // Omitted (compared to unittest.proto) because proto2 enums are not allowed + // inside proto2 messages. + // + // repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53; + + repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; + repeated string repeated_cord = 55 [ctype=CORD]; + + repeated NestedMessage repeated_lazy_message = 57 [lazy=true]; + + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + } +} + +// Test messages for packed fields + +message TestPackedTypes { + repeated int32 packed_int32 = 90 [packed = true]; + repeated int64 packed_int64 = 91 [packed = true]; + repeated uint32 packed_uint32 = 92 [packed = true]; + repeated uint64 packed_uint64 = 93 [packed = true]; + repeated sint32 packed_sint32 = 94 [packed = true]; + repeated sint64 packed_sint64 = 95 [packed = true]; + repeated fixed32 packed_fixed32 = 96 [packed = true]; + repeated fixed64 packed_fixed64 = 97 [packed = true]; + repeated sfixed32 packed_sfixed32 = 98 [packed = true]; + repeated sfixed64 packed_sfixed64 = 99 [packed = true]; + repeated float packed_float = 100 [packed = true]; + repeated double packed_double = 101 [packed = true]; + repeated bool packed_bool = 102 [packed = true]; + repeated ForeignEnum packed_enum = 103 [packed = true]; +} + +// Explicitly set packed to false +message TestUnpackedTypes { + repeated int32 repeated_int32 = 1 [packed = false]; + repeated int64 repeated_int64 = 2 [packed = false]; + repeated uint32 repeated_uint32 = 3 [packed = false]; + repeated uint64 repeated_uint64 = 4 [packed = false]; + repeated sint32 repeated_sint32 = 5 [packed = false]; + repeated sint64 repeated_sint64 = 6 [packed = false]; + repeated fixed32 repeated_fixed32 = 7 [packed = false]; + repeated fixed64 repeated_fixed64 = 8 [packed = false]; + repeated sfixed32 repeated_sfixed32 = 9 [packed = false]; + repeated sfixed64 repeated_sfixed64 = 10 [packed = false]; + repeated float repeated_float = 11 [packed = false]; + repeated double repeated_double = 12 [packed = false]; + repeated bool repeated_bool = 13 [packed = false]; + repeated TestAllTypes.NestedEnum repeated_nested_enum = 14 [packed = false]; +} + +// This proto includes a recusively nested message. +message NestedTestAllTypes { + NestedTestAllTypes child = 1; + TestAllTypes payload = 2; +} + +// Define these after TestAllTypes to make sure the compiler can handle +// that. +message ForeignMessage { + int32 c = 1; +} + +enum ForeignEnum { + FOREIGN_ZERO = 0; + FOREIGN_FOO = 4; + FOREIGN_BAR = 5; + FOREIGN_BAZ = 6; +} + +// TestEmptyMessage is used to test behavior of unknown fields. +message TestEmptyMessage { +} + diff --git a/src/google/protobuf/unittest_proto3_lite.proto b/src/google/protobuf/unittest_proto3_lite.proto new file mode 100644 index 00000000..874ade6c --- /dev/null +++ b/src/google/protobuf/unittest_proto3_lite.proto @@ -0,0 +1,206 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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"; + +option optimize_for = LITE_RUNTIME; + +import "google/protobuf/unittest_import.proto"; + +package proto3_lite_unittest; + +// This proto includes every type of field in both singular and repeated +// forms. +message TestAllTypes { + message NestedMessage { + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + + enum NestedEnum { + ZERO = 0; + FOO = 1; + BAR = 2; + BAZ = 3; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + sint32 optional_sint32 = 5; + sint64 optional_sint64 = 6; + fixed32 optional_fixed32 = 7; + fixed64 optional_fixed64 = 8; + sfixed32 optional_sfixed32 = 9; + sfixed64 optional_sfixed64 = 10; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; + + // Groups are not allowed in proto3. + // optional group OptionalGroup = 16 { + // optional int32 a = 17; + // } + + NestedMessage optional_nested_message = 18; + ForeignMessage optional_foreign_message = 19; + protobuf_unittest_import.ImportMessage optional_import_message = 20; + + NestedEnum optional_nested_enum = 21; + ForeignEnum optional_foreign_enum = 22; + + // Omitted (compared to unittest.proto) because proto2 enums are not allowed + // inside proto2 messages. + // + // optional protobuf_unittest_import.ImportEnum optional_import_enum = 23; + + string optional_string_piece = 24 [ctype=STRING_PIECE]; + string optional_cord = 25 [ctype=CORD]; + + // Defined in unittest_import_public.proto + protobuf_unittest_import.PublicImportMessage + optional_public_import_message = 26; + + 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; + + // Groups are not allowed in proto3. + // repeated group RepeatedGroup = 46 { + // optional int32 a = 47; + // } + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + + // Omitted (compared to unittest.proto) because proto2 enums are not allowed + // inside proto2 messages. + // + // repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53; + + repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; + repeated string repeated_cord = 55 [ctype=CORD]; + + repeated NestedMessage repeated_lazy_message = 57 [lazy=true]; + + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + } +} + +// Test messages for packed fields + +message TestPackedTypes { + repeated int32 packed_int32 = 90 [packed = true]; + repeated int64 packed_int64 = 91 [packed = true]; + repeated uint32 packed_uint32 = 92 [packed = true]; + repeated uint64 packed_uint64 = 93 [packed = true]; + repeated sint32 packed_sint32 = 94 [packed = true]; + repeated sint64 packed_sint64 = 95 [packed = true]; + repeated fixed32 packed_fixed32 = 96 [packed = true]; + repeated fixed64 packed_fixed64 = 97 [packed = true]; + repeated sfixed32 packed_sfixed32 = 98 [packed = true]; + repeated sfixed64 packed_sfixed64 = 99 [packed = true]; + repeated float packed_float = 100 [packed = true]; + repeated double packed_double = 101 [packed = true]; + repeated bool packed_bool = 102 [packed = true]; + repeated ForeignEnum packed_enum = 103 [packed = true]; +} + +// Explicitly set packed to false +message TestUnpackedTypes { + repeated int32 repeated_int32 = 1 [packed = false]; + repeated int64 repeated_int64 = 2 [packed = false]; + repeated uint32 repeated_uint32 = 3 [packed = false]; + repeated uint64 repeated_uint64 = 4 [packed = false]; + repeated sint32 repeated_sint32 = 5 [packed = false]; + repeated sint64 repeated_sint64 = 6 [packed = false]; + repeated fixed32 repeated_fixed32 = 7 [packed = false]; + repeated fixed64 repeated_fixed64 = 8 [packed = false]; + repeated sfixed32 repeated_sfixed32 = 9 [packed = false]; + repeated sfixed64 repeated_sfixed64 = 10 [packed = false]; + repeated float repeated_float = 11 [packed = false]; + repeated double repeated_double = 12 [packed = false]; + repeated bool repeated_bool = 13 [packed = false]; + repeated TestAllTypes.NestedEnum repeated_nested_enum = 14 [packed = false]; +} + +// This proto includes a recusively nested message. +message NestedTestAllTypes { + NestedTestAllTypes child = 1; + TestAllTypes payload = 2; +} + +// Define these after TestAllTypes to make sure the compiler can handle +// that. +message ForeignMessage { + int32 c = 1; +} + +enum ForeignEnum { + FOREIGN_ZERO = 0; + FOREIGN_FOO = 4; + FOREIGN_BAR = 5; + FOREIGN_BAZ = 6; +} + +// TestEmptyMessage is used to test behavior of unknown fields. +message TestEmptyMessage { +} + diff --git a/src/google/protobuf/util/field_comparator.cc b/src/google/protobuf/util/field_comparator.cc index 9f613265..60b8b8a5 100644 --- a/src/google/protobuf/util/field_comparator.cc +++ b/src/google/protobuf/util/field_comparator.cc @@ -92,7 +92,27 @@ FieldComparator::ComparisonResult DefaultFieldComparator::Compare( case FieldDescriptor::CPPTYPE_INT64: COMPARE_FIELD(Int64); case FieldDescriptor::CPPTYPE_STRING: - COMPARE_FIELD(String); + if (field->is_repeated()) { + // Allocate scratch strings to store the result if a conversion is + // needed. + string scratch1; + string scratch2; + return ResultFromBoolean( + CompareString(*field, reflection_1->GetRepeatedStringReference( + message_1, field, index_1, &scratch1), + reflection_2->GetRepeatedStringReference( + message_2, field, index_2, &scratch2))); + } else { + // Allocate scratch strings to store the result if a conversion is + // needed. + string scratch1; + string scratch2; + return ResultFromBoolean(CompareString( + *field, + reflection_1->GetStringReference(message_1, field, &scratch1), + reflection_2->GetStringReference(message_2, field, &scratch2))); + } + break; case FieldDescriptor::CPPTYPE_UINT32: COMPARE_FIELD(UInt32); case FieldDescriptor::CPPTYPE_UINT64: diff --git a/src/google/protobuf/util/field_mask_util_test.cc b/src/google/protobuf/util/field_mask_util_test.cc index b3787857..9b7fb62a 100644 --- a/src/google/protobuf/util/field_mask_util_test.cc +++ b/src/google/protobuf/util/field_mask_util_test.cc @@ -30,6 +30,8 @@ #include <google/protobuf/util/field_mask_util.h> +#include <algorithm> + #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/field_mask.pb.h> diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc index 297c011a..1f3781a4 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource.cc @@ -70,6 +70,9 @@ using util::Status; using util::StatusOr; namespace { + +static int kDefaultMaxRecursionDepth = 64; + // Finds a field with the given number. NULL if none found. const google::protobuf::Field* FindFieldByNumber( const google::protobuf::Type& type, int number); @@ -116,7 +119,9 @@ ProtoStreamObjectSource::ProtoStreamObjectSource( typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), own_typeinfo_(true), type_(type), - use_lower_camel_for_enums_(false) { + use_lower_camel_for_enums_(false), + recursion_depth_(0), + max_recursion_depth_(kDefaultMaxRecursionDepth) { GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL."; } @@ -127,7 +132,9 @@ ProtoStreamObjectSource::ProtoStreamObjectSource( typeinfo_(typeinfo), own_typeinfo_(false), type_(type), - use_lower_camel_for_enums_(false) { + use_lower_camel_for_enums_(false), + recursion_depth_(0), + max_recursion_depth_(kDefaultMaxRecursionDepth) { GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL."; } @@ -741,7 +748,9 @@ Status ProtoStreamObjectSource::RenderField( if (use_type_renderer) { RETURN_IF_ERROR((*type_renderer)(this, *type, field_name, ow)); } else { + RETURN_IF_ERROR(IncrementRecursionDepth(type->name(), field_name)); RETURN_IF_ERROR(WriteMessage(*type, field_name, 0, true, ow)); + --recursion_depth_; } if (!stream_->ConsumedEntireMessage()) { return Status(util::error::INVALID_ARGUMENT, @@ -1037,6 +1046,17 @@ std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos( return std::pair<int64, int32>(signed_seconds, signed_nanos); } +Status ProtoStreamObjectSource::IncrementRecursionDepth( + StringPiece type_name, StringPiece field_name) const { + if (++recursion_depth_ > max_recursion_depth_) { + return Status( + util::error::INVALID_ARGUMENT, + StrCat("Message too deep. Max recursion depth reached for type '", + type_name, "', field '", field_name, "'")); + } + return Status::OK; +} + namespace { // TODO(skarvaje): Speed this up by not doing a linear scan. const google::protobuf::Field* FindFieldByNumber( diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h index 17e03b73..d7d4347b 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource.h +++ b/src/google/protobuf/util/internal/protostream_objectsource.h @@ -110,6 +110,13 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { use_lower_camel_for_enums_ = value; } + // Sets the max recursion depth of proto message to be deserialized. Proto + // messages over this depth will fail to be deserialized. + // Default value is 64. + void set_max_recursion_depth(int max_depth) { + max_recursion_depth_ = max_depth; + } + protected: // Writes a proto2 Message to the ObjectWriter. When the given end_tag is // found this method will complete, allowing it to be used for parsing both @@ -251,6 +258,12 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { std::pair<int64, int32> ReadSecondsAndNanos( const google::protobuf::Type& type) const; + // Helper function to check recursion depth and increment it. It will return + // Status::OK if the current depth is allowed. Otherwise an error is returned. + // type_name and field_name are used for error reporting. + util::Status IncrementRecursionDepth(StringPiece type_name, + StringPiece field_name) const; + // Input stream to read from. Ownership rests with the caller. google::protobuf::io::CodedInputStream* stream_; @@ -268,6 +281,12 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { // Whether to render enums using lowerCamelCase. Defaults to false. bool use_lower_camel_for_enums_; + // Tracks current recursion depth. + mutable int recursion_depth_; + + // Maximum allowed recursion depth. + int max_recursion_depth_; + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectSource); }; diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc index 1b32c803..3f6fdf97 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc @@ -70,6 +70,7 @@ using google::protobuf::testing::Author; using google::protobuf::testing::BadAuthor; using google::protobuf::testing::BadNestedBook; using google::protobuf::testing::Book; +using google::protobuf::testing::Cyclic; using google::protobuf::testing::Book_Label; using google::protobuf::testing::NestedBook; using google::protobuf::testing::PackedPrimitive; @@ -120,6 +121,7 @@ class ProtostreamObjectSourceTest google::protobuf::scoped_ptr<ProtoStreamObjectSource> os( helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor))); if (use_lower_camel_for_enums_) os->set_use_lower_camel_for_enums(true); + os->set_max_recursion_depth(64); return os->WriteTo(&mock_); } @@ -491,6 +493,33 @@ TEST_P(ProtostreamObjectSourceTest, EnumCaseIsUnchangedByDefault) { DoTest(book, Book::descriptor()); } +TEST_P(ProtostreamObjectSourceTest, CyclicMessageDepthTest) { + Cyclic cyclic; + cyclic.set_m_int(123); + + Book* book = cyclic.mutable_m_book(); + book->set_title("book title"); + Cyclic* current = cyclic.mutable_m_cyclic(); + Author* current_author = cyclic.add_m_author(); + for (int i = 0; i < 63; ++i) { + Author* next = current_author->add_friend_(); + next->set_id(i); + next->set_name(StrCat("author_name_", i)); + next->set_alive(true); + current_author = next; + } + + // Recursive message with depth (65) > max (max is 64). + for (int i = 0; i < 64; ++i) { + Cyclic* next = current->mutable_m_cyclic(); + next->set_m_str(StrCat("count_", i)); + current = next; + } + + Status status = ExecuteTest(cyclic, Cyclic::descriptor()); + EXPECT_EQ(util::error::INVALID_ARGUMENT, status.error_code()); +} + class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest { protected: ProtostreamObjectSourceMapsTest() { diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc index 94ddb428..97a7909a 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc @@ -182,7 +182,8 @@ ProtoStreamObjectWriter::AnyWriter::AnyWriter(ProtoStreamObjectWriter* parent) data_(), output_(&data_), depth_(0), - has_injected_value_message_(false) {} + is_well_known_type_(false), + well_known_type_render_(NULL) {} ProtoStreamObjectWriter::AnyWriter::~AnyWriter() {} @@ -200,10 +201,19 @@ void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) { parent_->master_type_.name())); invalid_ = true; } - } else if (!has_injected_value_message_ || depth_ != 1 || name != "value") { - // We don't propagate to ow_ StartObject("value") calls for nested Anys or - // Struct at depth 1 as they are nested one level deep with an injected + } else if (is_well_known_type_ && depth_ == 1) { + // For well-known types, the only other field besides "@type" should be a // "value" field. + if (name != "value" && !invalid_) { + parent_->InvalidValue("Any", + "Expect a \"value\" field for well-known types."); + invalid_ = true; + } + ow_->StartObject(""); + } else { + // Forward the call to the child writer if: + // 1. the type is not a well-known type. + // 2. or, we are in a nested Any, Struct, or Value object. ow_->StartObject(name); } } @@ -211,10 +221,9 @@ void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) { bool ProtoStreamObjectWriter::AnyWriter::EndObject() { --depth_; // As long as depth_ >= 0, we know we haven't reached the end of Any. - // Propagate these EndObject() calls to the contained ow_. If we are in a - // nested Any or Struct type, ignore the second to last EndObject call (depth_ - // == -1) - if (ow_ != NULL && (!has_injected_value_message_ || depth_ >= 0)) { + // Propagate these EndObject() calls to the contained ow_. For regular + // message types, we propagate the end of Any as well. + if (ow_ != NULL && (depth_ >= 0 || !is_well_known_type_)) { ow_->EndObject(); } // A negative depth_ implies that we have reached the end of Any @@ -236,6 +245,13 @@ void ProtoStreamObjectWriter::AnyWriter::StartList(StringPiece name) { parent_->master_type_.name())); invalid_ = true; } + } else if (is_well_known_type_ && depth_ == 1) { + if (name != "value" && !invalid_) { + parent_->InvalidValue("Any", + "Expect a \"value\" field for well-known types."); + invalid_ = true; + } + ow_->StartList(""); } else { ow_->StartList(name); } @@ -266,17 +282,27 @@ void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece( parent_->master_type_.name())); invalid_ = true; } - } else { - // Check to see if the data needs to be rendered with well-known-type - // renderer. - const TypeRenderer* type_renderer = - FindTypeRenderer(GetFullTypeWithUrl(ow_->master_type_.name())); - if (type_renderer) { - Status status = (*type_renderer)(ow_.get(), value); - if (!status.ok()) ow_->InvalidValue("Any", status.error_message()); + } else if (depth_ == 0 && is_well_known_type_) { + if (name != "value" && !invalid_) { + parent_->InvalidValue("Any", + "Expect a \"value\" field for well-known types."); + invalid_ = true; + } + if (well_known_type_render_ == NULL) { + // Only Any and Struct don't have a special type render but both of + // them expect a JSON object (i.e., a StartObject() call). + if (!invalid_) { + parent_->InvalidValue("Any", "Expect a JSON object."); + invalid_ = true; + } } else { - ow_->RenderDataPiece(name, value); + ow_->ProtoWriter::StartObject(""); + Status status = (*well_known_type_render_)(ow_.get(), value); + if (!status.ok()) ow_->InvalidValue("Any", status.error_message()); + ow_->ProtoWriter::EndObject(); } + } else { + ow_->RenderDataPiece(name, value); } } @@ -305,19 +331,31 @@ void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) { // At this point, type is never null. const google::protobuf::Type* type = resolved_type.ValueOrDie(); - // If this is the case of an Any in an Any or Struct in an Any, we need to - // expect a StartObject call with "value" while we're at depth_ 0, which we - // should ignore (not propagate to our nested object writer). We also need to - // ignore the second-to-last EndObject call, and not propagate that either. - if (type->name() == kAnyType || type->name() == kStructType) { - has_injected_value_message_ = true; + well_known_type_render_ = FindTypeRenderer(type_url_); + if (well_known_type_render_ != NULL || + // Explicitly list Any and Struct here because they don't have a + // custom renderer. + type->name() == kAnyType || type->name() == kStructType) { + is_well_known_type_ = true; } // Create our object writer and initialize it with the first StartObject // call. ow_.reset(new ProtoStreamObjectWriter(parent_->typeinfo(), *type, &output_, parent_->listener())); - ow_->StartObject(""); + + // Don't call StartObject() for well-known types yet. Depending on the + // type of actual data, we may not need to call StartObject(). For + // example: + // { + // "@type": "type.googleapis.com/google.protobuf.Value", + // "value": [1, 2, 3], + // } + // With the above JSON representation, we will only call StartList() on the + // contained ow_. + if (!is_well_known_type_) { + ow_->StartObject(""); + } } void ProtoStreamObjectWriter::AnyWriter::WriteAny() { @@ -861,7 +899,7 @@ Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow, // conversions as much as possible. Because ToSnakeCase sometimes returns the // wrong value. google::protobuf::scoped_ptr<ResultCallback1<util::Status, StringPiece> > callback( - google::protobuf::internal::NewPermanentCallback(&RenderOneFieldPath, ow)); + ::google::protobuf::internal::NewPermanentCallback(&RenderOneFieldPath, ow)); return DecodeCompactFieldMaskPaths(data.str(), callback.get()); } @@ -986,6 +1024,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece( // not of the google.protobuf.NullType type, we do nothing. if (data.type() == DataPiece::TYPE_NULL && field->type_url() != kStructNullValueTypeUrl) { + Pop(); return this; } diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h index 96ea3f2b..e1162d43 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.h +++ b/src/google/protobuf/util/internal/protostream_objectwriter.h @@ -167,9 +167,14 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { // The depth within the Any, so we can track when we're done. int depth_; - // True if the message type contained in Any has a special "value" message - // injected. This is true for well-known message types like Any or Struct. - bool has_injected_value_message_; + // True if the type is a well-known type. Well-known types in Any + // has a special formating: + // { + // "@type": "type.googleapis.com/google.protobuf.XXX", + // "value": <JSON representation of the type>, + // } + bool is_well_known_type_; + TypeRenderer* well_known_type_render_; }; // Represents an item in a stack of items used to keep state between diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc index 41eaebc0..9a0dcde1 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc @@ -1413,6 +1413,8 @@ class ProtoStreamObjectWriterAnyTest : public BaseProtoStreamObjectWriterTest { descriptors.push_back(google::protobuf::DoubleValue::descriptor()); descriptors.push_back(google::protobuf::Timestamp::descriptor()); descriptors.push_back(google::protobuf::Any::descriptor()); + descriptors.push_back(google::protobuf::Value::descriptor()); + descriptors.push_back(google::protobuf::Struct::descriptor()); ResetTypeInfo(descriptors); } }; @@ -1621,6 +1623,222 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypeErrorTest) { CheckOutput(any); } +// Test the following case: +// +// { +// "any": { +// "@type": "type.googleapis.com/google.protobuf.Value", +// "value": "abc" +// } +// } +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithNestedPrimitiveValue) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + + ::google::protobuf::Value value; + value.set_string_value("abc"); + any->PackFrom(value); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Value") + ->RenderString("value", "abc") + ->EndObject() + ->EndObject(); + CheckOutput(out); +} + +// Test the following case: +// +// { +// "any": { +// "@type": "type.googleapis.com/google.protobuf.Value", +// "value": { +// "foo": "abc" +// } +// } +// } +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithNestedObjectValue) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + + ::google::protobuf::Value value; + (*value.mutable_struct_value()->mutable_fields())["foo"].set_string_value( + "abc"); + any->PackFrom(value); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Value") + ->StartObject("value") + ->RenderString("foo", "abc") + ->EndObject() + ->EndObject() + ->EndObject(); + CheckOutput(out); +} + +// Test the following case: +// +// { +// "any": { +// "@type": "type.googleapis.com/google.protobuf.Value", +// "value": ["hello"], +// } +// } +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithNestedArrayValue) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + + ::google::protobuf::Value value; + value.mutable_list_value()->add_values()->set_string_value("hello"); + any->PackFrom(value); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Value") + ->StartList("value") + ->RenderString("", "hello") + ->EndList() + ->EndObject() + ->EndObject() + ->EndObject(); + CheckOutput(out); +} + +// Test the following case: +// +// { +// "any": { +// "@type": "type.googleapis.com/google.protobuf.Value", +// "not_value": "" +// } +// } +TEST_P(ProtoStreamObjectWriterAnyTest, + AnyWellKnownTypesNoValueFieldForPrimitive) { + EXPECT_CALL( + listener_, + InvalidValue( + _, StringPiece("Any"), + StringPiece("Expect a \"value\" field for well-known types."))); + AnyOut any; + google::protobuf::Any* any_type = any.mutable_any(); + any_type->set_type_url("type.googleapis.com/google.protobuf.Value"); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Value") + ->RenderString("not_value", "") + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + +// Test the following case: +// +// { +// "any": { +// "@type": "type.googleapis.com/google.protobuf.Value", +// "not_value": {} +// } +// } +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesNoValueFieldForObject) { + EXPECT_CALL( + listener_, + InvalidValue( + _, StringPiece("Any"), + StringPiece("Expect a \"value\" field for well-known types."))); + AnyOut any; + google::protobuf::Any* any_type = any.mutable_any(); + any_type->set_type_url("type.googleapis.com/google.protobuf.Value"); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Value") + ->StartObject("not_value") + ->EndObject() + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + +// Test the following case: +// +// { +// "any": { +// "@type": "type.googleapis.com/google.protobuf.Value", +// "not_value": [], +// } +// } +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesNoValueFieldForArray) { + EXPECT_CALL( + listener_, + InvalidValue( + _, StringPiece("Any"), + StringPiece("Expect a \"value\" field for well-known types."))); + AnyOut any; + google::protobuf::Any* any_type = any.mutable_any(); + any_type->set_type_url("type.googleapis.com/google.protobuf.Value"); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Value") + ->StartList("not_value") + ->EndList() + ->EndObject() + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + +// Test the following case: +// +// { +// "any": { +// "@type": "type.googleapis.com/google.protobuf.Struct", +// "value": "", +// } +// } +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesExpectObjectForStruct) { + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"), + StringPiece("Expect a JSON object."))); + AnyOut any; + google::protobuf::Any* any_type = any.mutable_any(); + any_type->set_type_url("type.googleapis.com/google.protobuf.Struct"); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Struct") + ->RenderString("value", "") + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + +// Test the following case: +// +// { +// "any": { +// "@type": "type.googleapis.com/google.protobuf.Any", +// "value": "", +// } +// } +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesExpectObjectForAny) { + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"), + StringPiece("Expect a JSON object."))); + AnyOut any; + google::protobuf::Any* any_type = any.mutable_any(); + any_type->set_type_url("type.googleapis.com/google.protobuf.Any"); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Any") + ->RenderString("value", "") + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + class ProtoStreamObjectWriterFieldMaskTest : public BaseProtoStreamObjectWriterTest { protected: diff --git a/src/google/protobuf/util/internal/testdata/books.proto b/src/google/protobuf/util/internal/testdata/books.proto index 101a2bf0..1cbbba47 100644 --- a/src/google/protobuf/util/internal/testdata/books.proto +++ b/src/google/protobuf/util/internal/testdata/books.proto @@ -176,3 +176,12 @@ message NestedBook { message BadNestedBook { repeated uint32 book = 1 [packed=true]; // Packed to optional message. } + +// A recursively defined message. +message Cyclic { + optional int32 m_int = 1; + optional string m_str = 2; + optional Book m_book = 3; + repeated Author m_author = 5; + optional Cyclic m_cyclic = 4; +} diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc index b2b3242a..fe8119bf 100644 --- a/src/google/protobuf/util/message_differencer.cc +++ b/src/google/protobuf/util/message_differencer.cc @@ -456,7 +456,9 @@ bool MessageDifferencer::Compare( const Descriptor* descriptor2 = message2.GetDescriptor(); if (descriptor1 != descriptor2) { GOOGLE_LOG(DFATAL) << "Comparison between two messages with different " - << "descriptors."; + << "descriptors. " + << descriptor1->full_name() << " vs " + << descriptor2->full_name(); return false; } // Expand google.protobuf.Any payload if possible. @@ -1385,7 +1387,7 @@ bool MessageDifferencer::MatchRepeatedFieldIndices( // algorithm will fail to find a maximum matching. // Here we use the argumenting path algorithm. MaximumMatcher::NodeMatchCallback* callback = - google::protobuf::internal::NewPermanentCallback( + ::google::protobuf::internal::NewPermanentCallback( this, &MessageDifferencer::IsMatch, repeated_field, key_comparator, &message1, &message2, parent_fields); diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc index 204c8029..60801423 100644 --- a/src/google/protobuf/wrappers.pb.cc +++ b/src/google/protobuf/wrappers.pb.cc @@ -388,12 +388,13 @@ DoubleValue* DoubleValue::New(::google::protobuf::Arena* arena) const { } void DoubleValue::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.DoubleValue) value_ = 0; } bool DoubleValue::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.DoubleValue) for (;;) { @@ -460,6 +461,7 @@ void DoubleValue::SerializeWithCachedSizes( } int DoubleValue::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DoubleValue) int total_size = 0; // optional double value = 1; @@ -474,18 +476,22 @@ int DoubleValue::ByteSize() const { } void DoubleValue::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DoubleValue) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const DoubleValue* source = ::google::protobuf::internal::DynamicCastToGenerated<const DoubleValue>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DoubleValue) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DoubleValue) MergeFrom(*source); } } void DoubleValue::MergeFrom(const DoubleValue& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DoubleValue) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from.value() != 0) { set_value(from.value()); @@ -493,12 +499,14 @@ void DoubleValue::MergeFrom(const DoubleValue& from) { } void DoubleValue::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DoubleValue) if (&from == this) return; Clear(); MergeFrom(from); } void DoubleValue::CopyFrom(const DoubleValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.DoubleValue) if (&from == this) return; Clear(); MergeFrom(from); @@ -638,12 +646,13 @@ FloatValue* FloatValue::New(::google::protobuf::Arena* arena) const { } void FloatValue::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.FloatValue) value_ = 0; } bool FloatValue::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.FloatValue) for (;;) { @@ -710,6 +719,7 @@ void FloatValue::SerializeWithCachedSizes( } int FloatValue::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FloatValue) int total_size = 0; // optional float value = 1; @@ -724,18 +734,22 @@ int FloatValue::ByteSize() const { } void FloatValue::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FloatValue) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const FloatValue* source = ::google::protobuf::internal::DynamicCastToGenerated<const FloatValue>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FloatValue) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FloatValue) MergeFrom(*source); } } void FloatValue::MergeFrom(const FloatValue& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FloatValue) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from.value() != 0) { set_value(from.value()); @@ -743,12 +757,14 @@ void FloatValue::MergeFrom(const FloatValue& from) { } void FloatValue::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FloatValue) if (&from == this) return; Clear(); MergeFrom(from); } void FloatValue::CopyFrom(const FloatValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FloatValue) if (&from == this) return; Clear(); MergeFrom(from); @@ -888,12 +904,13 @@ Int64Value* Int64Value::New(::google::protobuf::Arena* arena) const { } void Int64Value::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Int64Value) value_ = GOOGLE_LONGLONG(0); } bool Int64Value::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.Int64Value) for (;;) { @@ -960,6 +977,7 @@ void Int64Value::SerializeWithCachedSizes( } int Int64Value::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Int64Value) int total_size = 0; // optional int64 value = 1; @@ -976,18 +994,22 @@ int Int64Value::ByteSize() const { } void Int64Value::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Int64Value) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const Int64Value* source = ::google::protobuf::internal::DynamicCastToGenerated<const Int64Value>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Int64Value) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Int64Value) MergeFrom(*source); } } void Int64Value::MergeFrom(const Int64Value& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Int64Value) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from.value() != 0) { set_value(from.value()); @@ -995,12 +1017,14 @@ void Int64Value::MergeFrom(const Int64Value& from) { } void Int64Value::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Int64Value) if (&from == this) return; Clear(); MergeFrom(from); } void Int64Value::CopyFrom(const Int64Value& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Int64Value) if (&from == this) return; Clear(); MergeFrom(from); @@ -1140,12 +1164,13 @@ UInt64Value* UInt64Value::New(::google::protobuf::Arena* arena) const { } void UInt64Value::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.UInt64Value) value_ = GOOGLE_ULONGLONG(0); } bool UInt64Value::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.UInt64Value) for (;;) { @@ -1212,6 +1237,7 @@ void UInt64Value::SerializeWithCachedSizes( } int UInt64Value::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UInt64Value) int total_size = 0; // optional uint64 value = 1; @@ -1228,18 +1254,22 @@ int UInt64Value::ByteSize() const { } void UInt64Value::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UInt64Value) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const UInt64Value* source = ::google::protobuf::internal::DynamicCastToGenerated<const UInt64Value>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UInt64Value) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UInt64Value) MergeFrom(*source); } } void UInt64Value::MergeFrom(const UInt64Value& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UInt64Value) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from.value() != 0) { set_value(from.value()); @@ -1247,12 +1277,14 @@ void UInt64Value::MergeFrom(const UInt64Value& from) { } void UInt64Value::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UInt64Value) if (&from == this) return; Clear(); MergeFrom(from); } void UInt64Value::CopyFrom(const UInt64Value& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.UInt64Value) if (&from == this) return; Clear(); MergeFrom(from); @@ -1392,12 +1424,13 @@ Int32Value* Int32Value::New(::google::protobuf::Arena* arena) const { } void Int32Value::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Int32Value) value_ = 0; } bool Int32Value::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.Int32Value) for (;;) { @@ -1464,6 +1497,7 @@ void Int32Value::SerializeWithCachedSizes( } int Int32Value::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Int32Value) int total_size = 0; // optional int32 value = 1; @@ -1480,18 +1514,22 @@ int Int32Value::ByteSize() const { } void Int32Value::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Int32Value) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const Int32Value* source = ::google::protobuf::internal::DynamicCastToGenerated<const Int32Value>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Int32Value) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Int32Value) MergeFrom(*source); } } void Int32Value::MergeFrom(const Int32Value& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Int32Value) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from.value() != 0) { set_value(from.value()); @@ -1499,12 +1537,14 @@ void Int32Value::MergeFrom(const Int32Value& from) { } void Int32Value::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Int32Value) if (&from == this) return; Clear(); MergeFrom(from); } void Int32Value::CopyFrom(const Int32Value& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Int32Value) if (&from == this) return; Clear(); MergeFrom(from); @@ -1644,12 +1684,13 @@ UInt32Value* UInt32Value::New(::google::protobuf::Arena* arena) const { } void UInt32Value::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.UInt32Value) value_ = 0u; } bool UInt32Value::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.UInt32Value) for (;;) { @@ -1716,6 +1757,7 @@ void UInt32Value::SerializeWithCachedSizes( } int UInt32Value::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UInt32Value) int total_size = 0; // optional uint32 value = 1; @@ -1732,18 +1774,22 @@ int UInt32Value::ByteSize() const { } void UInt32Value::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UInt32Value) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const UInt32Value* source = ::google::protobuf::internal::DynamicCastToGenerated<const UInt32Value>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UInt32Value) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UInt32Value) MergeFrom(*source); } } void UInt32Value::MergeFrom(const UInt32Value& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UInt32Value) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from.value() != 0) { set_value(from.value()); @@ -1751,12 +1797,14 @@ void UInt32Value::MergeFrom(const UInt32Value& from) { } void UInt32Value::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UInt32Value) if (&from == this) return; Clear(); MergeFrom(from); } void UInt32Value::CopyFrom(const UInt32Value& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.UInt32Value) if (&from == this) return; Clear(); MergeFrom(from); @@ -1896,12 +1944,13 @@ BoolValue* BoolValue::New(::google::protobuf::Arena* arena) const { } void BoolValue::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.BoolValue) value_ = false; } bool BoolValue::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.BoolValue) for (;;) { @@ -1968,6 +2017,7 @@ void BoolValue::SerializeWithCachedSizes( } int BoolValue::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.BoolValue) int total_size = 0; // optional bool value = 1; @@ -1982,18 +2032,22 @@ int BoolValue::ByteSize() const { } void BoolValue::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.BoolValue) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const BoolValue* source = ::google::protobuf::internal::DynamicCastToGenerated<const BoolValue>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.BoolValue) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.BoolValue) MergeFrom(*source); } } void BoolValue::MergeFrom(const BoolValue& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.BoolValue) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from.value() != 0) { set_value(from.value()); @@ -2001,12 +2055,14 @@ void BoolValue::MergeFrom(const BoolValue& from) { } void BoolValue::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.BoolValue) if (&from == this) return; Clear(); MergeFrom(from); } void BoolValue::CopyFrom(const BoolValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.BoolValue) if (&from == this) return; Clear(); MergeFrom(from); @@ -2148,12 +2204,13 @@ StringValue* StringValue::New(::google::protobuf::Arena* arena) const { } void StringValue::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.StringValue) value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); } bool StringValue::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.StringValue) for (;;) { @@ -2233,6 +2290,7 @@ void StringValue::SerializeWithCachedSizes( } int StringValue::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.StringValue) int total_size = 0; // optional string value = 1; @@ -2249,18 +2307,22 @@ int StringValue::ByteSize() const { } void StringValue::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.StringValue) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const StringValue* source = ::google::protobuf::internal::DynamicCastToGenerated<const StringValue>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.StringValue) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.StringValue) MergeFrom(*source); } } void StringValue::MergeFrom(const StringValue& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.StringValue) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from.value().size() > 0) { set_value(from.value()); @@ -2268,12 +2330,14 @@ void StringValue::MergeFrom(const StringValue& from) { } void StringValue::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.StringValue) if (&from == this) return; Clear(); MergeFrom(from); } void StringValue::CopyFrom(const StringValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.StringValue) if (&from == this) return; Clear(); MergeFrom(from); @@ -2349,10 +2413,12 @@ void StringValue::clear_value() { return value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); } ::std::string* StringValue::release_value() { + // @@protoc_insertion_point(field_release:google.protobuf.StringValue.value) return value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); } ::std::string* StringValue::unsafe_arena_release_value() { + // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.StringValue.value) GOOGLE_DCHECK(GetArenaNoVirtual() != NULL); return value_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), @@ -2378,7 +2444,7 @@ void StringValue::clear_value() { } value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual()); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.StringValue.value) + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.StringValue.value) } #endif // PROTOBUF_INLINE_NOT_IN_HEADERS @@ -2465,12 +2531,13 @@ BytesValue* BytesValue::New(::google::protobuf::Arena* arena) const { } void BytesValue::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.BytesValue) value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); } bool BytesValue::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.BytesValue) for (;;) { @@ -2538,6 +2605,7 @@ void BytesValue::SerializeWithCachedSizes( } int BytesValue::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.BytesValue) int total_size = 0; // optional bytes value = 1; @@ -2554,18 +2622,22 @@ int BytesValue::ByteSize() const { } void BytesValue::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.BytesValue) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); const BytesValue* source = ::google::protobuf::internal::DynamicCastToGenerated<const BytesValue>( &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.BytesValue) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.BytesValue) MergeFrom(*source); } } void BytesValue::MergeFrom(const BytesValue& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.BytesValue) if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); if (from.value().size() > 0) { set_value(from.value()); @@ -2573,12 +2645,14 @@ void BytesValue::MergeFrom(const BytesValue& from) { } void BytesValue::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.BytesValue) if (&from == this) return; Clear(); MergeFrom(from); } void BytesValue::CopyFrom(const BytesValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.BytesValue) if (&from == this) return; Clear(); MergeFrom(from); @@ -2654,10 +2728,12 @@ void BytesValue::clear_value() { return value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); } ::std::string* BytesValue::release_value() { + // @@protoc_insertion_point(field_release:google.protobuf.BytesValue.value) return value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); } ::std::string* BytesValue::unsafe_arena_release_value() { + // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.BytesValue.value) GOOGLE_DCHECK(GetArenaNoVirtual() != NULL); return value_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), @@ -2683,7 +2759,7 @@ void BytesValue::clear_value() { } value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual()); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.BytesValue.value) + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.BytesValue.value) } #endif // PROTOBUF_INLINE_NOT_IN_HEADERS diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h index 7dca938c..10784778 100644 --- a/src/google/protobuf/wrappers.pb.h +++ b/src/google/protobuf/wrappers.pb.h @@ -1048,10 +1048,12 @@ inline ::std::string* StringValue::mutable_value() { return value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); } inline ::std::string* StringValue::release_value() { + // @@protoc_insertion_point(field_release:google.protobuf.StringValue.value) return value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); } inline ::std::string* StringValue::unsafe_arena_release_value() { + // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.StringValue.value) GOOGLE_DCHECK(GetArenaNoVirtual() != NULL); return value_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), @@ -1077,7 +1079,7 @@ inline void StringValue::unsafe_arena_set_allocated_value( } value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual()); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.StringValue.value) + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.StringValue.value) } // ------------------------------------------------------------------- @@ -1116,10 +1118,12 @@ inline ::std::string* BytesValue::mutable_value() { return value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); } inline ::std::string* BytesValue::release_value() { + // @@protoc_insertion_point(field_release:google.protobuf.BytesValue.value) return value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); } inline ::std::string* BytesValue::unsafe_arena_release_value() { + // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.BytesValue.value) GOOGLE_DCHECK(GetArenaNoVirtual() != NULL); return value_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), @@ -1145,7 +1149,7 @@ inline void BytesValue::unsafe_arena_set_allocated_value( } value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual()); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.BytesValue.value) + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.BytesValue.value) } #endif // !PROTOBUF_INLINE_NOT_IN_HEADERS @@ -36,6 +36,9 @@ build_cpp() { internal_build_cpp make check -j2 cd conformance && make test_cpp && cd .. + + # Verify benchmarking code can build successfully. + cd benchmarks && make && ./generate-datasets && cd .. } build_cpp_distcheck() { |