aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--BUILD12
-rw-r--r--CHANGES.txt106
-rw-r--r--Makefile.am120
-rw-r--r--Protobuf.podspec26
-rw-r--r--cmake/extract_includes.bat.in2
-rw-r--r--cmake/install.cmake206
-rw-r--r--cmake/libprotobuf-lite.cmake2
-rw-r--r--cmake/libprotobuf.cmake3
-rw-r--r--cmake/libprotoc.cmake1
-rw-r--r--cmake/protobuf-config-version.cmake.in2
-rw-r--r--cmake/protobuf-config.cmake.in54
-rw-r--r--cmake/tests.cmake24
-rw-r--r--configure.ac2
-rw-r--r--csharp/README.md19
-rwxr-xr-xcsharp/generate_protos.sh18
-rw-r--r--csharp/src/AddressBook/Addressbook.cs16
-rw-r--r--csharp/src/Google.Protobuf.Conformance/Conformance.cs220
-rw-r--r--csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj1
-rw-r--r--csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs246
-rw-r--r--csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs14
-rw-r--r--csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs6
-rw-r--r--csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs44
-rw-r--r--csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs252
-rw-r--r--csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs270
-rw-r--r--csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs66
-rw-r--r--csharp/src/Google.Protobuf/Google.Protobuf.csproj1
-rw-r--r--csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs2
-rw-r--r--csharp/src/Google.Protobuf/Reflection/DescriptorProtoFile.cs222
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/Any.cs6
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs79
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/Api.cs232
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs8
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs8
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs8
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs10
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs26
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs8
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/Type.cs160
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs18
-rwxr-xr-xgenerate_descriptor_proto.sh5
-rw-r--r--java/pom.xml6
-rw-r--r--java/src/main/java/com/google/protobuf/ByteString.java28
-rw-r--r--java/src/main/java/com/google/protobuf/CodedOutputStream.java103
-rw-r--r--java/src/main/java/com/google/protobuf/Descriptors.java19
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessage.java115
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessageLite.java109
-rw-r--r--java/src/main/java/com/google/protobuf/Internal.java41
-rw-r--r--java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java2
-rw-r--r--java/src/main/java/com/google/protobuf/LazyStringArrayList.java5
-rw-r--r--java/src/main/java/com/google/protobuf/LazyStringList.java13
-rw-r--r--java/src/main/java/com/google/protobuf/Message.java3
-rw-r--r--java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java2
-rw-r--r--java/src/main/java/com/google/protobuf/RopeByteString.java2
-rw-r--r--java/src/main/java/com/google/protobuf/TextFormat.java12
-rw-r--r--java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java257
-rw-r--r--java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java5
-rw-r--r--java/src/main/java/com/google/protobuf/Utf8.java132
-rw-r--r--java/src/main/java/com/google/protobuf/WireFormat.java2
-rw-r--r--java/src/test/java/com/google/protobuf/AnyTest.java92
-rw-r--r--java/src/test/java/com/google/protobuf/BoundedByteStringTest.java1
-rw-r--r--java/src/test/java/com/google/protobuf/CheckUtf8Test.java7
-rw-r--r--java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java110
-rw-r--r--java/src/test/java/com/google/protobuf/FieldPresenceTest.java10
-rw-r--r--java/src/test/java/com/google/protobuf/GeneratedMessageTest.java3
-rw-r--r--java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java21
-rw-r--r--java/src/test/java/com/google/protobuf/LiteTest.java3
-rw-r--r--java/src/test/java/com/google/protobuf/LiteralByteStringTest.java61
-rw-r--r--java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java26
-rw-r--r--java/src/test/java/com/google/protobuf/MapForProto2Test.java26
-rw-r--r--java/src/test/java/com/google/protobuf/MapTest.java42
-rw-r--r--java/src/test/java/com/google/protobuf/ParserTest.java16
-rw-r--r--java/src/test/java/com/google/protobuf/RopeByteStringTest.java8
-rw-r--r--java/src/test/java/com/google/protobuf/TestUtil.java1
-rw-r--r--java/src/test/java/com/google/protobuf/TextFormatTest.java2
-rw-r--r--java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java2
-rw-r--r--java/src/test/java/com/google/protobuf/WireFormatTest.java2
-rw-r--r--java/src/test/java/com/google/protobuf/any_test.proto42
-rw-r--r--java/util/pom.xml202
-rw-r--r--java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java259
-rw-r--r--java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java222
-rw-r--r--java/util/src/main/java/com/google/protobuf/util/JsonFormat.java1571
-rw-r--r--java/util/src/main/java/com/google/protobuf/util/TimeUtil.java545
-rw-r--r--java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java229
-rw-r--r--java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java135
-rw-r--r--java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java976
-rw-r--r--java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java439
-rw-r--r--java/util/src/test/java/com/google/protobuf/util/json_test.proto158
-rw-r--r--javanano/pom.xml4
-rwxr-xr-xobjectivec/DevTools/compile_testing_protos.sh4
-rw-r--r--objectivec/Tests/GPBUnittestProtos.m4
-rw-r--r--objectivec/Tests/GPBWireFormatTests.m1
-rw-r--r--objectivec/google/protobuf/Any.pbobjc.h11
-rw-r--r--objectivec/google/protobuf/Api.pbobjc.h119
-rw-r--r--objectivec/google/protobuf/Api.pbobjc.m127
-rw-r--r--objectivec/google/protobuf/Descriptor.pbobjc.h12
-rw-r--r--objectivec/google/protobuf/Descriptor.pbobjc.m13
-rw-r--r--objectivec/google/protobuf/Empty.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/FieldMask.pbobjc.h4
-rw-r--r--objectivec/google/protobuf/Struct.pbobjc.h13
-rw-r--r--objectivec/google/protobuf/Timestamp.pbobjc.h9
-rw-r--r--objectivec/google/protobuf/Type.pbobjc.h38
-rw-r--r--objectivec/google/protobuf/Type.pbobjc.m92
-rw-r--r--objectivec/google/protobuf/Wrappers.pbobjc.h36
-rwxr-xr-xpost_process_dist.sh6
-rw-r--r--protoc-artifacts/pom.xml2
-rwxr-xr-xpython/google/protobuf/__init__.py2
-rwxr-xr-xpython/google/protobuf/internal/containers.py11
-rwxr-xr-xpython/google/protobuf/internal/generator_test.py3
-rw-r--r--python/google/protobuf/internal/message_set_extensions.proto66
-rwxr-xr-xpython/google/protobuf/internal/message_test.py115
-rw-r--r--python/google/protobuf/internal/packed_field_test.proto73
-rwxr-xr-xpython/google/protobuf/internal/python_message.py151
-rwxr-xr-xpython/google/protobuf/internal/reflection_test.py55
-rwxr-xr-xpython/google/protobuf/internal/test_util.py3
-rwxr-xr-xpython/google/protobuf/internal/text_format_test.py32
-rwxr-xr-xpython/google/protobuf/internal/unknown_fields_test.py72
-rw-r--r--python/google/protobuf/pyext/cpp_message.py36
-rw-r--r--python/google/protobuf/pyext/descriptor.cc68
-rw-r--r--python/google/protobuf/pyext/descriptor_pool.cc53
-rw-r--r--python/google/protobuf/pyext/descriptor_pool.h25
-rw-r--r--python/google/protobuf/pyext/extension_dict.cc6
-rw-r--r--python/google/protobuf/pyext/message.cc749
-rw-r--r--python/google/protobuf/pyext/message.h4
-rw-r--r--python/google/protobuf/pyext/message_map_container.cc105
-rw-r--r--python/google/protobuf/pyext/message_map_container.h7
-rw-r--r--python/google/protobuf/pyext/repeated_composite_container.cc211
-rw-r--r--python/google/protobuf/pyext/repeated_scalar_container.cc11
-rw-r--r--python/google/protobuf/pyext/scalar_map_container.cc104
-rw-r--r--python/google/protobuf/pyext/scalar_map_container.h7
-rw-r--r--python/google/protobuf/pyext/scoped_pyobject_ptr.h16
-rwxr-xr-xpython/google/protobuf/reflection.py96
-rwxr-xr-xpython/google/protobuf/text_format.py2
-rwxr-xr-xpython/setup.py6
-rw-r--r--python/tox.ini3
-rw-r--r--ruby/Gemfile.lock2
-rw-r--r--ruby/google-protobuf.gemspec2
-rw-r--r--ruby/pom.xml2
-rw-r--r--src/Makefile.am72
-rw-r--r--src/google/protobuf/any.cc4
-rw-r--r--src/google/protobuf/any.h2
-rw-r--r--src/google/protobuf/any.pb.cc14
-rw-r--r--src/google/protobuf/any.proto10
-rw-r--r--src/google/protobuf/api.pb.cc733
-rw-r--r--src/google/protobuf/api.pb.h315
-rw-r--r--src/google/protobuf/api.proto107
-rwxr-xr-xsrc/google/protobuf/arena.cc40
-rw-r--r--src/google/protobuf/arena.h174
-rw-r--r--src/google/protobuf/arena_test_util.cc1
-rw-r--r--src/google/protobuf/arena_unittest.cc55
-rwxr-xr-xsrc/google/protobuf/arenastring.h12
-rw-r--r--src/google/protobuf/arenastring_unittest.cc1
-rw-r--r--src/google/protobuf/compiler/code_generator.cc1
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc5
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc43
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.cc8
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.h5
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.cc1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.cc1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc259
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.h32
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_generator.cc13
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc112
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h26
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.cc72
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc181
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.h9
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc616
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.h20
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc115
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc8
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_generator.cc52
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_helpers.h2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc2
-rw-r--r--src/google/protobuf/compiler/importer_unittest.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_enum.cc4
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field_lite.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_enum_lite.cc226
-rw-r--r--src/google/protobuf/compiler/java/java_enum_lite.h99
-rw-r--r--src/google/protobuf/compiler/java/java_field.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_field.h1
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.h15
-rw-r--r--src/google/protobuf/compiler/java/java_map_field.cc24
-rw-r--r--src/google/protobuf/compiler/java/java_map_field_lite.cc24
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc137
-rw-r--r--src/google/protobuf/compiler/java/java_message.h1
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.cc13
-rw-r--r--src/google/protobuf/compiler/java/java_message_field_lite.cc14
-rw-r--r--src/google/protobuf/compiler/java/java_message_lite.cc92
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field_lite.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_service.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_string_field.cc26
-rw-r--r--src/google/protobuf/compiler/java/java_string_field_lite.cc193
-rw-r--r--src/google/protobuf/compiler/main.cc2
-rw-r--r--src/google/protobuf/compiler/parser.cc37
-rw-r--r--src/google/protobuf/compiler/parser.h6
-rw-r--r--src/google/protobuf/compiler/plugin.cc1
-rw-r--r--src/google/protobuf/compiler/plugin.pb.cc44
-rw-r--r--src/google/protobuf/compiler/plugin.pb.h28
-rw-r--r--src/google/protobuf/compiler/python/python_generator.cc1
-rw-r--r--src/google/protobuf/compiler/python/python_generator.h1
-rw-r--r--src/google/protobuf/compiler/subprocess.cc1
-rw-r--r--src/google/protobuf/descriptor.cc24
-rw-r--r--src/google/protobuf/descriptor.h4
-rw-r--r--src/google/protobuf/descriptor.pb.cc506
-rw-r--r--src/google/protobuf/descriptor.pb.h346
-rw-r--r--src/google/protobuf/descriptor.proto8
-rw-r--r--src/google/protobuf/descriptor_database_unittest.cc2
-rw-r--r--src/google/protobuf/descriptor_unittest.cc85
-rw-r--r--src/google/protobuf/duration.proto1
-rw-r--r--src/google/protobuf/dynamic_message.cc27
-rw-r--r--src/google/protobuf/dynamic_message.h1
-rw-r--r--src/google/protobuf/dynamic_message_unittest.cc2
-rw-r--r--src/google/protobuf/empty.pb.cc6
-rw-r--r--src/google/protobuf/empty.proto7
-rw-r--r--src/google/protobuf/extension_set.cc109
-rw-r--r--src/google/protobuf/extension_set.h39
-rw-r--r--src/google/protobuf/extension_set_heavy.cc16
-rw-r--r--src/google/protobuf/extension_set_unittest.cc3
-rw-r--r--src/google/protobuf/field_mask.pb.cc24
-rw-r--r--src/google/protobuf/field_mask.proto6
-rw-r--r--src/google/protobuf/generated_message_reflection.cc145
-rw-r--r--src/google/protobuf/generated_message_reflection.h38
-rw-r--r--src/google/protobuf/generated_message_reflection_unittest.cc52
-rw-r--r--src/google/protobuf/generated_message_util.cc12
-rw-r--r--src/google/protobuf/generated_message_util.h6
-rw-r--r--src/google/protobuf/io/coded_stream.cc5
-rw-r--r--src/google/protobuf/io/coded_stream.h31
-rw-r--r--src/google/protobuf/io/coded_stream_inl.h1
-rw-r--r--src/google/protobuf/io/coded_stream_unittest.cc2
-rw-r--r--src/google/protobuf/io/gzip_stream.cc2
-rw-r--r--src/google/protobuf/io/printer.cc1
-rw-r--r--src/google/protobuf/io/printer_unittest.cc1
-rw-r--r--src/google/protobuf/io/strtod.cc1
-rw-r--r--src/google/protobuf/io/tokenizer.cc1
-rw-r--r--src/google/protobuf/io/tokenizer.h1
-rw-r--r--src/google/protobuf/io/tokenizer_unittest.cc1
-rw-r--r--src/google/protobuf/io/zero_copy_stream.cc1
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl.cc1
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl_lite.cc1
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl_lite.h1
-rw-r--r--src/google/protobuf/io/zero_copy_stream_unittest.cc3
-rw-r--r--src/google/protobuf/lite_arena_unittest.cc83
-rw-r--r--src/google/protobuf/lite_unittest.cc39
-rw-r--r--src/google/protobuf/map.h444
-rw-r--r--src/google/protobuf/map_entry.h81
-rw-r--r--src/google/protobuf/map_entry_lite.h158
-rw-r--r--src/google/protobuf/map_field.cc316
-rw-r--r--src/google/protobuf/map_field.h194
-rw-r--r--src/google/protobuf/map_field_inl.h233
-rw-r--r--src/google/protobuf/map_field_test.cc23
-rw-r--r--src/google/protobuf/map_lite_unittest.proto17
-rw-r--r--src/google/protobuf/map_proto2_unittest.proto8
-rw-r--r--src/google/protobuf/map_test.cc190
-rw-r--r--src/google/protobuf/map_test_util.cc726
-rw-r--r--src/google/protobuf/map_test_util.h131
-rw-r--r--src/google/protobuf/map_test_util_impl.h16
-rw-r--r--src/google/protobuf/map_type_handler.h753
-rw-r--r--src/google/protobuf/map_unittest.proto16
-rw-r--r--src/google/protobuf/message.cc27
-rw-r--r--src/google/protobuf/message.h113
-rw-r--r--src/google/protobuf/message_lite.cc62
-rw-r--r--src/google/protobuf/message_unittest.cc1
-rw-r--r--src/google/protobuf/metadata.h17
-rw-r--r--src/google/protobuf/no_field_presence_test.cc40
-rw-r--r--src/google/protobuf/proto3_arena_unittest.cc26
-rw-r--r--src/google/protobuf/proto_cast.h1
-rw-r--r--src/google/protobuf/proto_cast_test.cc2
-rwxr-xr-xsrc/google/protobuf/reflection.h2
-rw-r--r--src/google/protobuf/reflection_ops_unittest.cc1
-rw-r--r--src/google/protobuf/repeated_field.cc9
-rw-r--r--src/google/protobuf/repeated_field.h85
-rw-r--r--src/google/protobuf/repeated_field_unittest.cc2
-rw-r--r--src/google/protobuf/service.h5
-rw-r--r--src/google/protobuf/source_context.pb.cc20
-rw-r--r--src/google/protobuf/source_context.proto2
-rw-r--r--src/google/protobuf/struct.pb.cc66
-rw-r--r--src/google/protobuf/struct.pb.h30
-rw-r--r--src/google/protobuf/struct.proto28
-rw-r--r--src/google/protobuf/stubs/atomicops.h10
-rw-r--r--src/google/protobuf/stubs/common.cc63
-rw-r--r--src/google/protobuf/stubs/common.h24
-rwxr-xr-xsrc/google/protobuf/stubs/hash.h17
-rw-r--r--src/google/protobuf/stubs/int128.cc200
-rw-r--r--src/google/protobuf/stubs/int128.h383
-rw-r--r--src/google/protobuf/stubs/int128_unittest.cc513
-rw-r--r--src/google/protobuf/stubs/logging.h4
-rw-r--r--src/google/protobuf/stubs/mathutil.h16
-rw-r--r--src/google/protobuf/stubs/port.h19
-rw-r--r--src/google/protobuf/stubs/status.cc1
-rw-r--r--src/google/protobuf/stubs/structurally_valid.cc52
-rw-r--r--src/google/protobuf/test_util.cc1
-rw-r--r--src/google/protobuf/test_util_lite.cc1
-rw-r--r--src/google/protobuf/testing/googletest.cc7
-rw-r--r--src/google/protobuf/text_format_unittest.cc2
-rw-r--r--src/google/protobuf/timestamp.proto11
-rw-r--r--src/google/protobuf/type.pb.cc527
-rw-r--r--src/google/protobuf/type.pb.h211
-rw-r--r--src/google/protobuf/type.proto102
-rw-r--r--src/google/protobuf/unittest_mset.proto19
-rw-r--r--src/google/protobuf/unittest_mset_wire_format.proto52
-rw-r--r--src/google/protobuf/unittest_no_arena.proto1
-rw-r--r--src/google/protobuf/unittest_no_arena_lite.proto42
-rw-r--r--src/google/protobuf/unknown_enum_impl.h9
-rw-r--r--src/google/protobuf/unknown_enum_test.proto2
-rw-r--r--src/google/protobuf/unknown_field_set.cc1
-rw-r--r--src/google/protobuf/unknown_field_set.h1
-rw-r--r--src/google/protobuf/unknown_field_set_unittest.cc3
-rw-r--r--src/google/protobuf/util/field_comparator_test.cc2
-rw-r--r--src/google/protobuf/util/field_mask_util.cc418
-rw-r--r--src/google/protobuf/util/field_mask_util.h146
-rw-r--r--src/google/protobuf/util/field_mask_util_test.cc395
-rw-r--r--src/google/protobuf/util/internal/datapiece.cc6
-rw-r--r--src/google/protobuf/util/internal/datapiece.h14
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter.cc66
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter.h11
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter_test.cc58
-rw-r--r--src/google/protobuf/util/internal/error_listener.h2
-rw-r--r--src/google/protobuf/util/internal/field_mask_utility.cc23
-rw-r--r--src/google/protobuf/util/internal/json_escaping.cc1
-rw-r--r--src/google/protobuf/util/internal/json_objectwriter.cc12
-rw-r--r--src/google/protobuf/util/internal/json_objectwriter_test.cc189
-rw-r--r--src/google/protobuf/util/internal/json_stream_parser.cc62
-rw-r--r--src/google/protobuf/util/internal/json_stream_parser.h12
-rw-r--r--src/google/protobuf/util/internal/json_stream_parser_test.cc23
-rw-r--r--src/google/protobuf/util/internal/protostream_objectsource.cc69
-rw-r--r--src/google/protobuf/util/internal/protostream_objectsource.h14
-rw-r--r--src/google/protobuf/util/internal/protostream_objectsource_test.cc40
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter.cc143
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter.h45
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter_test.cc306
-rw-r--r--src/google/protobuf/util/internal/snake2camel_objectwriter.h46
-rw-r--r--src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc260
-rw-r--r--src/google/protobuf/util/internal/testdata/default_value.proto7
-rw-r--r--src/google/protobuf/util/internal/testdata/oneofs.proto68
-rw-r--r--src/google/protobuf/util/internal/type_info.cc25
-rw-r--r--src/google/protobuf/util/internal/type_info.h13
-rw-r--r--src/google/protobuf/util/internal/type_info_test_helper.cc7
-rw-r--r--src/google/protobuf/util/internal/utility.cc15
-rw-r--r--src/google/protobuf/util/internal/utility.h11
-rw-r--r--src/google/protobuf/util/json_util.h6
-rw-r--r--src/google/protobuf/util/json_util_test.cc43
-rw-r--r--src/google/protobuf/util/message_differencer.cc1
-rwxr-xr-xsrc/google/protobuf/util/message_differencer_unittest.cc3
-rw-r--r--src/google/protobuf/util/time_util.cc525
-rw-r--r--src/google/protobuf/util/time_util.h296
-rw-r--r--src/google/protobuf/util/time_util_test.cc380
-rw-r--r--src/google/protobuf/util/type_resolver_util.cc43
-rw-r--r--src/google/protobuf/wire_format.cc57
-rw-r--r--src/google/protobuf/wire_format.h19
-rw-r--r--src/google/protobuf/wire_format_lite.cc38
-rw-r--r--src/google/protobuf/wire_format_lite.h177
-rw-r--r--src/google/protobuf/wire_format_lite_inl.h1
-rw-r--r--src/google/protobuf/wire_format_unittest.cc16
-rw-r--r--src/google/protobuf/wrappers.pb.cc21
-rw-r--r--src/google/protobuf/wrappers.pb.h10
-rw-r--r--src/google/protobuf/wrappers.proto38
-rwxr-xr-xtravis.sh12
-rwxr-xr-xupdate_file_lists.sh39
363 files changed, 21836 insertions, 5494 deletions
diff --git a/BUILD b/BUILD
index 5cfed337..571f48b8 100644
--- a/BUILD
+++ b/BUILD
@@ -35,11 +35,13 @@ cc_library(
"src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc",
"src/google/protobuf/stubs/bytestream.cc",
"src/google/protobuf/stubs/common.cc",
+ "src/google/protobuf/stubs/int128.cc",
"src/google/protobuf/stubs/once.cc",
"src/google/protobuf/stubs/status.cc",
"src/google/protobuf/stubs/statusor.cc",
"src/google/protobuf/stubs/stringpiece.cc",
"src/google/protobuf/stubs/stringprintf.cc",
+ "src/google/protobuf/stubs/structurally_valid.cc",
"src/google/protobuf/stubs/strutil.cc",
"src/google/protobuf/stubs/time.cc",
"src/google/protobuf/wire_format_lite.cc",
@@ -80,13 +82,13 @@ cc_library(
"src/google/protobuf/source_context.pb.cc",
"src/google/protobuf/struct.pb.cc",
"src/google/protobuf/stubs/mathlimits.cc",
- "src/google/protobuf/stubs/structurally_valid.cc",
"src/google/protobuf/stubs/substitute.cc",
"src/google/protobuf/text_format.cc",
"src/google/protobuf/timestamp.pb.cc",
"src/google/protobuf/type.pb.cc",
"src/google/protobuf/unknown_field_set.cc",
"src/google/protobuf/util/field_comparator.cc",
+ "src/google/protobuf/util/field_mask_util.cc",
"src/google/protobuf/util/internal/datapiece.cc",
"src/google/protobuf/util/internal/default_value_objectwriter.cc",
"src/google/protobuf/util/internal/error_listener.cc",
@@ -102,6 +104,7 @@ cc_library(
"src/google/protobuf/util/internal/utility.cc",
"src/google/protobuf/util/json_util.cc",
"src/google/protobuf/util/message_differencer.cc",
+ "src/google/protobuf/util/time_util.cc",
"src/google/protobuf/util/type_resolver_util.cc",
"src/google/protobuf/wire_format.cc",
"src/google/protobuf/wrappers.pb.cc",
@@ -180,6 +183,7 @@ cc_library(
"src/google/protobuf/compiler/java/java_enum.cc",
"src/google/protobuf/compiler/java/java_enum_field.cc",
"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_field.cc",
"src/google/protobuf/compiler/java/java_file.cc",
@@ -258,6 +262,7 @@ LITE_TEST_PROTOS = [
"google/protobuf/unittest_import_lite.proto",
"google/protobuf/unittest_import_public_lite.proto",
"google/protobuf/unittest_lite.proto",
+ "google/protobuf/unittest_no_arena_lite.proto",
]
TEST_PROTOS = [
@@ -278,6 +283,7 @@ TEST_PROTOS = [
"google/protobuf/unittest_import_public.proto",
"google/protobuf/unittest_lite_imports_nonlite.proto",
"google/protobuf/unittest_mset.proto",
+ "google/protobuf/unittest_mset_wire_format.proto",
"google/protobuf/unittest_no_arena.proto",
"google/protobuf/unittest_no_arena_import.proto",
"google/protobuf/unittest_no_field_presence.proto",
@@ -293,6 +299,7 @@ TEST_PROTOS = [
"google/protobuf/util/internal/testdata/default_value_test.proto",
"google/protobuf/util/internal/testdata/field_mask.proto",
"google/protobuf/util/internal/testdata/maps.proto",
+ "google/protobuf/util/internal/testdata/oneofs.proto",
"google/protobuf/util/internal/testdata/struct.proto",
"google/protobuf/util/internal/testdata/timestamp_duration.proto",
"google/protobuf/util/json_format_proto3.proto",
@@ -381,6 +388,7 @@ cc_test(
"src/google/protobuf/repeated_field_unittest.cc",
"src/google/protobuf/stubs/bytestream_unittest.cc",
"src/google/protobuf/stubs/common_unittest.cc",
+ "src/google/protobuf/stubs/int128_unittest.cc",
"src/google/protobuf/stubs/once_unittest.cc",
"src/google/protobuf/stubs/status_test.cc",
"src/google/protobuf/stubs/statusor_test.cc",
@@ -394,6 +402,7 @@ cc_test(
"src/google/protobuf/text_format_unittest.cc",
"src/google/protobuf/unknown_field_set_unittest.cc",
"src/google/protobuf/util/field_comparator_test.cc",
+ "src/google/protobuf/util/field_mask_util_test.cc",
"src/google/protobuf/util/internal/default_value_objectwriter_test.cc",
"src/google/protobuf/util/internal/json_objectwriter_test.cc",
"src/google/protobuf/util/internal/json_stream_parser_test.cc",
@@ -401,6 +410,7 @@ cc_test(
"src/google/protobuf/util/internal/protostream_objectwriter_test.cc",
"src/google/protobuf/util/internal/type_info_test_helper.cc",
"src/google/protobuf/util/json_util_test.cc",
+ "src/google/protobuf/util/time_util_test.cc",
"src/google/protobuf/util/type_resolver_util_test.cc",
"src/google/protobuf/well_known_types_unittest.cc",
"src/google/protobuf/wire_format_unittest.cc",
diff --git a/CHANGES.txt b/CHANGES.txt
index 846d735e..ca3078c3 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,109 @@
+2015-08-26 version 3.0.0-beta-1 (C++/Java/Python/Ruby/Nano/Objective-C/C#)
+ About Beta
+ * This is the first beta release of protobuf v3.0.0. Not all languages
+ have reached beta stage. Languages not marked as beta are still in
+ alpha (i.e., be prepared for API breaking changes).
+
+ General
+ * Proto3 JSON is supported in several languages (fully supported in C++
+ and Java, partially supported in Ruby/C#). The JSON spec is defined in
+ the proto3 language guide:
+
+ https://developers.google.com/protocol-buffers/docs/proto3#json
+
+ We will publish a more detailed spec to define the exact behavior of
+ proto3-conformant JSON serializers and parsers. Until then, do not rely
+ on specific behaviors of the implementation if it’s not documented in
+ the above spec. More specifically, the behavior is not yet finalized for
+ the following:
+ - Parsing invalid JSON input (e.g., input with trailing commas).
+ - Non-camelCase names in JSON input.
+ - The same field appears multiple times in JSON input.
+ - JSON arrays contain “null” values.
+ - The message has unknown fields.
+
+ * Proto3 now enforces strict UTF-8 checking. Parsing will fail if a string
+ field contains non UTF-8 data.
+
+ C++ (Beta)
+ * Introduced new utility functions/classes in the google/protobuf/util
+ directory:
+ - MessageDifferencer: compare two proto messages and report their
+ differences.
+ - JsonUtil: support converting protobuf binary format to/from JSON.
+ - TimeUtil: utility functions to work with well-known types Timestamp
+ and Duration.
+ - FieldMaskUtil: utility functions to work with FieldMask.
+
+ * Performance optimization of arena construction and destruction.
+ * Bug fixes for arena and maps support.
+ * Changed to use cmake for Windows Visual Studio builds.
+ * Added Bazel support.
+
+ Java (Beta)
+ * Introduced a new util package that will be distributed as a separate
+ artifact in maven. It contains:
+ - JsonFormat: convert proto messages to/from JSON.
+ - TimeUtil: utility functions to work with Timestamp and Duration.
+ - FieldMaskUtil: utility functions to work with FieldMask.
+
+ * The static PARSER in each generated message is deprecated, and it will
+ be removed in a future release. A static parser() getter is generated
+ for each message type instead.
+ * Performance optimizations for String fields serialization.
+ * Performance optimizations for Lite runtime on Android:
+ - Reduced allocations
+ - Reduced method overhead after ProGuarding
+ - Reduced code size after ProGuarding
+
+ Python (Alpha)
+ * Removed legacy Python 2.5 support.
+ * Moved to a single Python 2.x/3.x-compatible codebase, instead of using 2to3.
+ * Fixed build/tests on Python 2.6, 2.7, 3.3, and 3.4.
+ - Pure-Python works on all four.
+ - Python/C++ implementation works on all but 3.4, due to changes in the
+ Python/C++ API in 3.4.
+ * Some preliminary work has been done to allow for multiple DescriptorPools
+ with Python/C++.
+
+ Ruby (Alpha)
+ * Many bugfixes:
+ - fixed parsing/serialization of bytes, sint, sfixed types
+ - other parser bugfixes
+ - fixed memory leak affecting Ruby 2.2
+
+ JavaNano (Alpha)
+ * JavaNano generated code now will be put in a nano package by default to
+ avoid conflicts with Java generated code.
+
+ Objective-C (Alpha)
+ * Added non-null markup to ObjC library. Requires SDK 8.4+ to build.
+ * Many bugfixes:
+ - Removed the class/enum filter.
+ - Renamed some internal types to avoid conflicts with the well-known types
+ protos.
+ - Added missing support for parsing repeated primitive fields in packed or
+ unpacked forms.
+ - Added *Count for repeated and map<> fields to avoid auto-create when
+ checking for them being set.
+
+ C# (Alpha)
+ * Namespace changed to Google.Protobuf (and NuGet package will be named
+ correspondingly).
+ * Target platforms now .NET 4.5 and selected portable subsets only.
+ * Removed lite runtime.
+ * Reimplementation to use mutable message types.
+ * Null references used to represent "no value" for message type fields.
+ * Proto3 semantics supported; proto2 files are prohibited for C# codegen.
+ Most proto3 features supported:
+ - JSON formatting (a.k.a. serialization to JSON), including well-known
+ types (except for Any).
+ - Wrapper types mapped to nullable value types (or string/ByteString
+ allowing nullability). JSON parsing is not supported yet.
+ - maps
+ - oneof
+ - enum unknown value preservation
+
2015-05-25 version 3.0.0-alpha-3 (Objective-C/C#):
General
* Introduced two new language implementations (Objective-C, C#) to proto3.
diff --git a/Makefile.am b/Makefile.am
index e97f18f5..8b361780 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -41,6 +41,7 @@ pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = protobuf.pc protobuf-lite.pc
csharp_EXTRA_DIST= \
+ csharp/.gitignore \
csharp/CHANGES.txt \
csharp/README.md \
csharp/build_packages.bat \
@@ -57,6 +58,11 @@ csharp_EXTRA_DIST= \
csharp/src/AddressBook/Properties/AssemblyInfo.cs \
csharp/src/AddressBook/SampleUsage.cs \
csharp/src/AddressBook/app.config \
+ csharp/src/Google.Protobuf.Conformance/App.config \
+ csharp/src/Google.Protobuf.Conformance/Conformance.cs \
+ csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj \
+ csharp/src/Google.Protobuf.Conformance/Program.cs \
+ csharp/src/Google.Protobuf.Conformance/Properties/AssemblyInfo.cs \
csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj \
csharp/src/Google.Protobuf.JsonDump/Program.cs \
csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs \
@@ -67,6 +73,8 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs \
csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs \
csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs \
+ csharp/src/Google.Protobuf.Test/Compatibility/PropertyInfoExtensionsTest.cs \
+ csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs \
csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs \
csharp/src/Google.Protobuf.Test/EqualityTester.cs \
csharp/src/Google.Protobuf.Test/FieldCodecTest.cs \
@@ -77,6 +85,7 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf.Test/Properties/AppManifest.xml \
csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs \
csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs \
+ csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs \
csharp/src/Google.Protobuf.Test/SampleEnum.cs \
csharp/src/Google.Protobuf.Test/SampleMessages.cs \
csharp/src/Google.Protobuf.Test/TestCornerCases.cs \
@@ -86,6 +95,9 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs \
csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs \
csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs \
+ csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs \
+ csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs \
+ csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs \
csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs \
csharp/src/Google.Protobuf.Test/packages.config \
csharp/src/Google.Protobuf.sln \
@@ -97,10 +109,13 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf/Collections/MapField.cs \
csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs \
csharp/src/Google.Protobuf/Collections/RepeatedField.cs \
+ csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs \
+ csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs \
csharp/src/Google.Protobuf/FieldCodec.cs \
csharp/src/Google.Protobuf/FrameworkPortability.cs \
csharp/src/Google.Protobuf/Google.Protobuf.csproj \
csharp/src/Google.Protobuf/Google.Protobuf.nuspec \
+ csharp/src/Google.Protobuf/IDeepCloneable.cs \
csharp/src/Google.Protobuf/IMessage.cs \
csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs \
csharp/src/Google.Protobuf/JsonFormatter.cs \
@@ -135,13 +150,17 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs \
csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs \
csharp/src/Google.Protobuf/WellKnownTypes/Any.cs \
+ csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs \
csharp/src/Google.Protobuf/WellKnownTypes/Api.cs \
csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs \
+ csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs \
csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs \
csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs \
csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs \
csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs \
+ csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs \
csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs \
+ csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs \
csharp/src/Google.Protobuf/WellKnownTypes/Type.cs \
csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs \
csharp/src/Google.Protobuf/WireFormat.cs \
@@ -154,8 +173,8 @@ java_EXTRA_DIST= \
java/src/main/java/com/google/protobuf/AbstractProtobufList.java \
java/src/main/java/com/google/protobuf/BlockingRpcChannel.java \
java/src/main/java/com/google/protobuf/BlockingService.java \
- java/src/main/java/com/google/protobuf/BoundedByteString.java \
java/src/main/java/com/google/protobuf/BooleanArrayList.java \
+ java/src/main/java/com/google/protobuf/BoundedByteString.java \
java/src/main/java/com/google/protobuf/ByteString.java \
java/src/main/java/com/google/protobuf/CodedInputStream.java \
java/src/main/java/com/google/protobuf/CodedOutputStream.java \
@@ -170,8 +189,8 @@ java_EXTRA_DIST= \
java/src/main/java/com/google/protobuf/FloatArrayList.java \
java/src/main/java/com/google/protobuf/GeneratedMessage.java \
java/src/main/java/com/google/protobuf/GeneratedMessageLite.java \
- java/src/main/java/com/google/protobuf/Internal.java \
java/src/main/java/com/google/protobuf/IntArrayList.java \
+ java/src/main/java/com/google/protobuf/Internal.java \
java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
java/src/main/java/com/google/protobuf/LazyField.java \
java/src/main/java/com/google/protobuf/LazyFieldLite.java \
@@ -199,8 +218,8 @@ java_EXTRA_DIST= \
java/src/main/java/com/google/protobuf/RpcChannel.java \
java/src/main/java/com/google/protobuf/RpcController.java \
java/src/main/java/com/google/protobuf/RpcUtil.java \
- java/src/main/java/com/google/protobuf/ServiceException.java \
java/src/main/java/com/google/protobuf/Service.java \
+ java/src/main/java/com/google/protobuf/ServiceException.java \
java/src/main/java/com/google/protobuf/SingleFieldBuilder.java \
java/src/main/java/com/google/protobuf/SmallSortedMap.java \
java/src/main/java/com/google/protobuf/TextFormat.java \
@@ -209,11 +228,11 @@ java_EXTRA_DIST= \
java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java \
java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java \
java/src/main/java/com/google/protobuf/Utf8.java \
- java/src/test/java/com/google/protobuf/WellKnownTypesTest.java \
java/src/main/java/com/google/protobuf/WireFormat.java \
java/src/test/java/com/google/protobuf/AbstractMessageTest.java \
- java/src/test/java/com/google/protobuf/BoundedByteStringTest.java \
+ java/src/test/java/com/google/protobuf/AnyTest.java \
java/src/test/java/com/google/protobuf/BooleanArrayListTest.java \
+ java/src/test/java/com/google/protobuf/BoundedByteStringTest.java \
java/src/test/java/com/google/protobuf/ByteStringTest.java \
java/src/test/java/com/google/protobuf/CheckUtf8Test.java \
java/src/test/java/com/google/protobuf/CodedInputStreamTest.java \
@@ -235,8 +254,8 @@ java_EXTRA_DIST= \
java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java \
java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java \
java/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java \
- java/src/test/java/com/google/protobuf/LiteralByteStringTest.java \
java/src/test/java/com/google/protobuf/LiteTest.java \
+ java/src/test/java/com/google/protobuf/LiteralByteStringTest.java \
java/src/test/java/com/google/protobuf/LongArrayListTest.java \
java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java \
java/src/test/java/com/google/protobuf/MapForProto2Test.java \
@@ -258,7 +277,9 @@ java_EXTRA_DIST= \
java/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java \
java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java \
java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java \
+ java/src/test/java/com/google/protobuf/WellKnownTypesTest.java \
java/src/test/java/com/google/protobuf/WireFormatTest.java \
+ java/src/test/java/com/google/protobuf/any_test.proto \
java/src/test/java/com/google/protobuf/field_presence_test.proto \
java/src/test/java/com/google/protobuf/lazy_fields_lite.proto \
java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto \
@@ -268,18 +289,28 @@ java_EXTRA_DIST= \
java/src/test/java/com/google/protobuf/map_test.proto \
java/src/test/java/com/google/protobuf/multiple_files_test.proto \
java/src/test/java/com/google/protobuf/nested_builders_test.proto \
- java/src/test/java/com/google/protobuf/nested_extension_lite.proto \
java/src/test/java/com/google/protobuf/nested_extension.proto \
- java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto \
+ java/src/test/java/com/google/protobuf/nested_extension_lite.proto \
java/src/test/java/com/google/protobuf/non_nested_extension.proto \
+ java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto \
+ java/src/test/java/com/google/protobuf/outer_class_name_test.proto \
java/src/test/java/com/google/protobuf/outer_class_name_test2.proto \
java/src/test/java/com/google/protobuf/outer_class_name_test3.proto \
- java/src/test/java/com/google/protobuf/outer_class_name_test.proto \
java/src/test/java/com/google/protobuf/test_bad_identifiers.proto \
java/src/test/java/com/google/protobuf/test_check_utf8.proto \
java/src/test/java/com/google/protobuf/test_check_utf8_size.proto \
java/src/test/java/com/google/protobuf/test_custom_options.proto \
java/src/test/java/com/google/protobuf/test_extra_interfaces.proto \
+ java/util/pom.xml \
+ java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java \
+ java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java \
+ java/util/src/main/java/com/google/protobuf/util/JsonFormat.java \
+ java/util/src/main/java/com/google/protobuf/util/TimeUtil.java \
+ java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java \
+ java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java \
+ java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java \
+ java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java \
+ java/util/src/test/java/com/google/protobuf/util/json_test.proto \
java/pom.xml \
java/README.md
@@ -324,6 +355,7 @@ javanano_EXTRA_DIST=
objectivec_EXTRA_DIST= \
objectivec/DevTools/check_version_stamps.sh \
+ objectivec/DevTools/compile_testing_protos.sh \
objectivec/DevTools/full_mac_build.sh \
objectivec/DevTools/pddm.py \
objectivec/DevTools/pddm_tests.py \
@@ -452,6 +484,7 @@ objectivec_EXTRA_DIST= \
objectivec/Tests/text_format_unittest_data.txt \
objectivec/Tests/unittest_cycle.proto \
objectivec/Tests/unittest_objc.proto \
+ objectivec/Tests/unittest_objc_startup.proto \
objectivec/Tests/unittest_runtime_proto2.proto \
objectivec/Tests/unittest_runtime_proto3.proto \
objectivec/Tests/UnitTests-Bridging-Header.h \
@@ -476,11 +509,13 @@ python_EXTRA_DIST= \
python/google/protobuf/internal/generator_test.py \
python/google/protobuf/internal/message_factory_test.py \
python/google/protobuf/internal/message_listener.py \
+ python/google/protobuf/internal/message_set_extensions.proto \
python/google/protobuf/internal/message_test.py \
python/google/protobuf/internal/missing_enum_values.proto \
- python/google/protobuf/internal/more_extensions.proto \
python/google/protobuf/internal/more_extensions_dynamic.proto \
+ python/google/protobuf/internal/more_extensions.proto \
python/google/protobuf/internal/more_messages.proto \
+ python/google/protobuf/internal/packed_field_test.proto \
python/google/protobuf/internal/_parameterized.py \
python/google/protobuf/internal/proto_builder_test.py \
python/google/protobuf/internal/python_message.py \
@@ -538,9 +573,10 @@ python_EXTRA_DIST= \
python/google/protobuf/text_format.py \
python/google/protobuf/__init__.py \
python/google/__init__.py \
- python/setup.py \
python/mox.py \
+ python/setup.py \
python/stubout.py \
+ python/tox.ini \
python/README.md
ruby_EXTRA_DIST= \
@@ -593,33 +629,41 @@ ruby_EXTRA_DIST= \
all_EXTRA_DIST=$(csharp_EXTRA_DIST) $(java_EXTRA_DIST) $(javanano_EXTRA_DIST) $(objectivec_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST)
-EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \
- autogen.sh \
- generate_descriptor_proto.sh \
- README.md \
- INSTALL.txt \
- LICENSE \
- CONTRIBUTORS.txt \
- CHANGES.txt \
- update_file_lists.sh \
- cmake/CMakeLists.txt \
- cmake/libprotobuf.cmake \
- cmake/libprotobuf-lite.cmake \
- cmake/libprotoc.cmake \
- cmake/protoc.cmake \
- cmake/README.md \
- cmake/tests.cmake \
- editors/README.txt \
- editors/proto.vim \
- editors/protobuf-mode.el \
- examples/README.txt \
- examples/Makefile \
- examples/addressbook.proto \
- examples/add_person.cc \
- examples/list_people.cc \
- examples/AddPerson.java \
- examples/ListPeople.java \
- examples/add_person.py \
+EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \
+ autogen.sh \
+ generate_descriptor_proto.sh \
+ README.md \
+ INSTALL.txt \
+ LICENSE \
+ CONTRIBUTORS.txt \
+ CHANGES.txt \
+ update_file_lists.sh \
+ BUILD \
+ gmock.BUILD \
+ WORKSPACE \
+ cmake/CMakeLists.txt \
+ cmake/README.md \
+ cmake/extract_includes.bat.in \
+ cmake/install.cmake \
+ cmake/libprotobuf.cmake \
+ cmake/libprotobuf-lite.cmake \
+ cmake/libprotoc.cmake \
+ cmake/protobuf-config-version.cmake.in \
+ cmake/protobuf-config.cmake.in \
+ cmake/protobuf-module.cmake.in \
+ cmake/protoc.cmake \
+ cmake/tests.cmake \
+ editors/README.txt \
+ editors/proto.vim \
+ editors/protobuf-mode.el \
+ examples/README.txt \
+ examples/Makefile \
+ examples/addressbook.proto \
+ examples/add_person.cc \
+ examples/list_people.cc \
+ examples/AddPerson.java \
+ examples/ListPeople.java \
+ examples/add_person.py \
examples/list_people.py
# Deletes all the files generated by autogen.sh.
diff --git a/Protobuf.podspec b/Protobuf.podspec
index 0cd52025..698583b9 100644
--- a/Protobuf.podspec
+++ b/Protobuf.podspec
@@ -5,17 +5,31 @@
# dependent projects use the :git notation to refer to the library.
Pod::Spec.new do |s|
s.name = 'Protobuf'
- s.version = '3.0.0-alpha-4-pre'
+ s.version = '3.0.0-alpha-4'
s.summary = 'Protocol Buffers v.3 runtime library for Objective-C.'
s.homepage = 'https://github.com/google/protobuf'
s.license = 'New BSD'
s.authors = { 'The Protocol Buffers contributors' => 'protobuf@googlegroups.com' }
- s.source_files = 'objectivec/GPBProtocolBuffers.{h,m}'
- # GPBProtocolBuffers.{h,m} are umbrella files. We need Cocoapods to preserve the files imported by
- # them.
- s.preserve_paths = 'objectivec/*.{h,m}',
- 'objectivec/google/protobuf/*.pbobjc.{h,m}'
+ s.source_files = 'objectivec/*.{h,m}',
+ 'objectivec/google/protobuf/Any.pbobjc.{h,m}',
+ 'objectivec/google/protobuf/Api.pbobjc.{h,m}',
+ 'objectivec/google/protobuf/Descriptor.pbobjc.{h,m}',
+ 'objectivec/google/protobuf/Duration.pbobjc.h',
+ 'objectivec/google/protobuf/Empty.pbobjc.{h,m}',
+ 'objectivec/google/protobuf/FieldMask.pbobjc.{h,m}',
+ 'objectivec/google/protobuf/SourceContext.pbobjc.{h,m}',
+ 'objectivec/google/protobuf/Struct.pbobjc.{h,m}',
+ 'objectivec/google/protobuf/Timestamp.pbobjc.h',
+ 'objectivec/google/protobuf/Type.pbobjc.{h,m}',
+ 'objectivec/google/protobuf/Wrappers.pbobjc.{h,m}'
+ # Timestamp.pbobjc.m and Duration.pbobjc.m are #imported by GPBWellKnownTypes.m. So we can't
+ # compile them (duplicate symbols), but we need them available for the importing:
+ s.preserve_paths = 'objectivec/google/protobuf/Duration.pbobjc.m',
+ 'objectivec/google/protobuf/Timestamp.pbobjc.m'
+ # The following would cause duplicate symbol definitions. GPBProtocolBuffers is expected to be
+ # left out, as it's an umbrella implementation file.
+ s.exclude_files = 'objectivec/GPBProtocolBuffers.m'
s.header_mappings_dir = 'objectivec'
s.ios.deployment_target = '7.1'
diff --git a/cmake/extract_includes.bat.in b/cmake/extract_includes.bat.in
index 853332ae..eaf97583 100644
--- a/cmake/extract_includes.bat.in
+++ b/cmake/extract_includes.bat.in
@@ -110,8 +110,10 @@ copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\timestamp.pb.h include
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\type.pb.h include\google\protobuf\type.pb.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\unknown_field_set.h include\google\protobuf\unknown_field_set.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\field_comparator.h include\google\protobuf\util\field_comparator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\field_mask_util.h include\google\protobuf\util\field_mask_util.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\json_util.h include\google\protobuf\util\json_util.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\message_differencer.h include\google\protobuf\util\message_differencer.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\time_util.h include\google\protobuf\util\time_util.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver.h include\google\protobuf\util\type_resolver.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver_util.h include\google\protobuf\util\type_resolver_util.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format.h include\google\protobuf\wire_format.h
diff --git a/cmake/install.cmake b/cmake/install.cmake
index e14ef1d2..dbb4265d 100644
--- a/cmake/install.cmake
+++ b/cmake/install.cmake
@@ -1,103 +1,103 @@
-include(GNUInstallDirs)
-
-foreach(_library
- libprotobuf-lite
- libprotobuf
- libprotoc)
- set_property(TARGET ${_library}
- PROPERTY INTERFACE_INCLUDE_DIRECTORIES
- $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
- install(TARGETS ${_library} EXPORT protobuf-targets
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${_library}
- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${_library}
- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${_library})
-endforeach()
-
-install(TARGETS protoc EXPORT protobuf-targets
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc)
-
-if(TRUE)
- file(STRINGS extract_includes.bat.in _extract_strings
- REGEX "^copy")
- foreach(_extract_string ${_extract_strings})
- string(REPLACE "copy \${PROTOBUF_SOURCE_WIN32_PATH}\\" ""
- _extract_string ${_extract_string})
- string(REPLACE "\\" "/" _extract_string ${_extract_string})
- string(REGEX MATCH "^[^ ]+"
- _extract_from ${_extract_string})
- string(REGEX REPLACE "^${_extract_from} ([^$]+)" "\\1"
- _extract_to ${_extract_string})
- get_filename_component(_extract_from "${protobuf_SOURCE_DIR}/${_extract_from}" ABSOLUTE)
- get_filename_component(_extract_name ${_extract_to} NAME)
- get_filename_component(_extract_to ${_extract_to} PATH)
- string(REPLACE "include/" "${CMAKE_INSTALL_INCLUDEDIR}/"
- _extract_to "${_extract_to}")
- if(EXISTS "${_extract_from}")
- install(FILES "${_extract_from}"
- DESTINATION "${_extract_to}"
- COMPONENT protobuf-headers
- RENAME "${_extract_name}")
- else()
- message(AUTHOR_WARNING "The file \"${_extract_from}\" is listed in "
- "\"${protobuf_SOURCE_DIR}/cmake/extract_includes.bat.in\" "
- "but there not exists. The file will not be installed.")
- endif()
- endforeach()
-endif()
-
-# Internal function for parsing auto tools scripts
-function(_protobuf_auto_list FILE_NAME VARIABLE)
- file(STRINGS ${FILE_NAME} _strings)
- set(_list)
- foreach(_string ${_strings})
- set(_found)
- string(REGEX MATCH "^[ \t]*${VARIABLE}[ \t]*=[ \t]*" _found "${_string}")
- if(_found)
- string(LENGTH "${_found}" _length)
- string(SUBSTRING "${_string}" ${_length} -1 _draft_list)
- foreach(_item ${_draft_list})
- string(STRIP "${_item}" _item)
- list(APPEND _list "${_item}")
- endforeach()
- endif()
- endforeach()
- set(${VARIABLE} ${_list} PARENT_SCOPE)
-endfunction()
-
-# Install well-known type proto files
-_protobuf_auto_list("../src/Makefile.am" nobase_dist_proto_DATA)
-foreach(_file ${nobase_dist_proto_DATA})
- get_filename_component(_file_from "../src/${_file}" ABSOLUTE)
- get_filename_component(_file_name ${_file} NAME)
- get_filename_component(_file_path ${_file} PATH)
- if(EXISTS "${_file_from}")
- install(FILES "${_file_from}"
- DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_file_path}"
- COMPONENT protobuf-protos
- RENAME "${_file_name}")
- else()
- message(AUTHOR_WARNING "The file \"${_file_from}\" is listed in "
- "\"${protobuf_SOURCE_DIR}/../src/Makefile.am\" as nobase_dist_proto_DATA "
- "but there not exists. The file will not be installed.")
- endif()
-endforeach()
-
-# Export configuration
-
-install(EXPORT protobuf-targets
- DESTINATION "lib/cmake/protobuf"
- COMPONENT protobuf-export)
-
-configure_file(protobuf-config.cmake.in
- protobuf-config.cmake @ONLY)
-configure_file(protobuf-config-version.cmake.in
- protobuf-config-version.cmake @ONLY)
-configure_file(protobuf-module.cmake.in
- protobuf-module.cmake @ONLY)
-
-install(FILES
- "${protobuf_BINARY_DIR}/protobuf-config.cmake"
- "${protobuf_BINARY_DIR}/protobuf-config-version.cmake"
- "${protobuf_BINARY_DIR}/protobuf-module.cmake"
- DESTINATION "lib/cmake/protobuf"
- COMPONENT protobuf-export)
+include(GNUInstallDirs)
+
+foreach(_library
+ libprotobuf-lite
+ libprotobuf
+ libprotoc)
+ set_property(TARGET ${_library}
+ PROPERTY INTERFACE_INCLUDE_DIRECTORIES
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
+ install(TARGETS ${_library} EXPORT protobuf-targets
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${_library}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${_library}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${_library})
+endforeach()
+
+install(TARGETS protoc EXPORT protobuf-targets
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc)
+
+if(TRUE)
+ file(STRINGS extract_includes.bat.in _extract_strings
+ REGEX "^copy")
+ foreach(_extract_string ${_extract_strings})
+ string(REPLACE "copy \${PROTOBUF_SOURCE_WIN32_PATH}\\" ""
+ _extract_string ${_extract_string})
+ string(REPLACE "\\" "/" _extract_string ${_extract_string})
+ string(REGEX MATCH "^[^ ]+"
+ _extract_from ${_extract_string})
+ string(REGEX REPLACE "^${_extract_from} ([^$]+)" "\\1"
+ _extract_to ${_extract_string})
+ get_filename_component(_extract_from "${protobuf_SOURCE_DIR}/${_extract_from}" ABSOLUTE)
+ get_filename_component(_extract_name ${_extract_to} NAME)
+ get_filename_component(_extract_to ${_extract_to} PATH)
+ string(REPLACE "include/" "${CMAKE_INSTALL_INCLUDEDIR}/"
+ _extract_to "${_extract_to}")
+ if(EXISTS "${_extract_from}")
+ install(FILES "${_extract_from}"
+ DESTINATION "${_extract_to}"
+ COMPONENT protobuf-headers
+ RENAME "${_extract_name}")
+ else()
+ message(AUTHOR_WARNING "The file \"${_extract_from}\" is listed in "
+ "\"${protobuf_SOURCE_DIR}/cmake/extract_includes.bat.in\" "
+ "but there not exists. The file will not be installed.")
+ endif()
+ endforeach()
+endif()
+
+# Internal function for parsing auto tools scripts
+function(_protobuf_auto_list FILE_NAME VARIABLE)
+ file(STRINGS ${FILE_NAME} _strings)
+ set(_list)
+ foreach(_string ${_strings})
+ set(_found)
+ string(REGEX MATCH "^[ \t]*${VARIABLE}[ \t]*=[ \t]*" _found "${_string}")
+ if(_found)
+ string(LENGTH "${_found}" _length)
+ string(SUBSTRING "${_string}" ${_length} -1 _draft_list)
+ foreach(_item ${_draft_list})
+ string(STRIP "${_item}" _item)
+ list(APPEND _list "${_item}")
+ endforeach()
+ endif()
+ endforeach()
+ set(${VARIABLE} ${_list} PARENT_SCOPE)
+endfunction()
+
+# Install well-known type proto files
+_protobuf_auto_list("../src/Makefile.am" nobase_dist_proto_DATA)
+foreach(_file ${nobase_dist_proto_DATA})
+ get_filename_component(_file_from "../src/${_file}" ABSOLUTE)
+ get_filename_component(_file_name ${_file} NAME)
+ get_filename_component(_file_path ${_file} PATH)
+ if(EXISTS "${_file_from}")
+ install(FILES "${_file_from}"
+ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_file_path}"
+ COMPONENT protobuf-protos
+ RENAME "${_file_name}")
+ else()
+ message(AUTHOR_WARNING "The file \"${_file_from}\" is listed in "
+ "\"${protobuf_SOURCE_DIR}/../src/Makefile.am\" as nobase_dist_proto_DATA "
+ "but there not exists. The file will not be installed.")
+ endif()
+endforeach()
+
+# Export configuration
+
+install(EXPORT protobuf-targets
+ DESTINATION "lib/cmake/protobuf"
+ COMPONENT protobuf-export)
+
+configure_file(protobuf-config.cmake.in
+ protobuf-config.cmake @ONLY)
+configure_file(protobuf-config-version.cmake.in
+ protobuf-config-version.cmake @ONLY)
+configure_file(protobuf-module.cmake.in
+ protobuf-module.cmake @ONLY)
+
+install(FILES
+ "${protobuf_BINARY_DIR}/protobuf-config.cmake"
+ "${protobuf_BINARY_DIR}/protobuf-config-version.cmake"
+ "${protobuf_BINARY_DIR}/protobuf-module.cmake"
+ DESTINATION "lib/cmake/protobuf"
+ COMPONENT protobuf-export)
diff --git a/cmake/libprotobuf-lite.cmake b/cmake/libprotobuf-lite.cmake
index e323840a..9fafc316 100644
--- a/cmake/libprotobuf-lite.cmake
+++ b/cmake/libprotobuf-lite.cmake
@@ -12,11 +12,13 @@ set(libprotobuf_lite_files
${protobuf_source_dir}/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc
${protobuf_source_dir}/src/google/protobuf/stubs/bytestream.cc
${protobuf_source_dir}/src/google/protobuf/stubs/common.cc
+ ${protobuf_source_dir}/src/google/protobuf/stubs/int128.cc
${protobuf_source_dir}/src/google/protobuf/stubs/once.cc
${protobuf_source_dir}/src/google/protobuf/stubs/status.cc
${protobuf_source_dir}/src/google/protobuf/stubs/statusor.cc
${protobuf_source_dir}/src/google/protobuf/stubs/stringpiece.cc
${protobuf_source_dir}/src/google/protobuf/stubs/stringprintf.cc
+ ${protobuf_source_dir}/src/google/protobuf/stubs/structurally_valid.cc
${protobuf_source_dir}/src/google/protobuf/stubs/strutil.cc
${protobuf_source_dir}/src/google/protobuf/stubs/time.cc
${protobuf_source_dir}/src/google/protobuf/wire_format_lite.cc
diff --git a/cmake/libprotobuf.cmake b/cmake/libprotobuf.cmake
index 31fb1fb2..64a9cae0 100644
--- a/cmake/libprotobuf.cmake
+++ b/cmake/libprotobuf.cmake
@@ -25,13 +25,13 @@ set(libprotobuf_files
${protobuf_source_dir}/src/google/protobuf/source_context.pb.cc
${protobuf_source_dir}/src/google/protobuf/struct.pb.cc
${protobuf_source_dir}/src/google/protobuf/stubs/mathlimits.cc
- ${protobuf_source_dir}/src/google/protobuf/stubs/structurally_valid.cc
${protobuf_source_dir}/src/google/protobuf/stubs/substitute.cc
${protobuf_source_dir}/src/google/protobuf/text_format.cc
${protobuf_source_dir}/src/google/protobuf/timestamp.pb.cc
${protobuf_source_dir}/src/google/protobuf/type.pb.cc
${protobuf_source_dir}/src/google/protobuf/unknown_field_set.cc
${protobuf_source_dir}/src/google/protobuf/util/field_comparator.cc
+ ${protobuf_source_dir}/src/google/protobuf/util/field_mask_util.cc
${protobuf_source_dir}/src/google/protobuf/util/internal/datapiece.cc
${protobuf_source_dir}/src/google/protobuf/util/internal/default_value_objectwriter.cc
${protobuf_source_dir}/src/google/protobuf/util/internal/error_listener.cc
@@ -47,6 +47,7 @@ set(libprotobuf_files
${protobuf_source_dir}/src/google/protobuf/util/internal/utility.cc
${protobuf_source_dir}/src/google/protobuf/util/json_util.cc
${protobuf_source_dir}/src/google/protobuf/util/message_differencer.cc
+ ${protobuf_source_dir}/src/google/protobuf/util/time_util.cc
${protobuf_source_dir}/src/google/protobuf/util/type_resolver_util.cc
${protobuf_source_dir}/src/google/protobuf/wire_format.cc
${protobuf_source_dir}/src/google/protobuf/wrappers.pb.cc
diff --git a/cmake/libprotoc.cmake b/cmake/libprotoc.cmake
index f8fa7adb..7aa92ee1 100644
--- a/cmake/libprotoc.cmake
+++ b/cmake/libprotoc.cmake
@@ -34,6 +34,7 @@ set(libprotoc_files
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum_field.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum_field_lite.cc
+ ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum_lite.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_extension.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_field.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_file.cc
diff --git a/cmake/protobuf-config-version.cmake.in b/cmake/protobuf-config-version.cmake.in
index 07ab40b9..1f171c66 100644
--- a/cmake/protobuf-config-version.cmake.in
+++ b/cmake/protobuf-config-version.cmake.in
@@ -1 +1 @@
-set(PACKAGE_VERSION @protobuf_VERSION@)
+set(PACKAGE_VERSION @protobuf_VERSION@)
diff --git a/cmake/protobuf-config.cmake.in b/cmake/protobuf-config.cmake.in
index 51d715cf..bb0997b8 100644
--- a/cmake/protobuf-config.cmake.in
+++ b/cmake/protobuf-config.cmake.in
@@ -1,27 +1,27 @@
-# Version info variables
-set(PROTOBUF_VERSION "@protobuf_VERSION@")
-set(PROTOBUF_VERSION_STRING "@protobuf_VERSION_STRING@")
-
-# Current dir
-get_filename_component(_PROTOBUF_PACKAGE_PREFIX
- "${CMAKE_CURRENT_LIST_FILE}" PATH)
-
-# Imported targets
-include("${_PROTOBUF_PACKAGE_PREFIX}/protobuf-targets.cmake")
-
-# Compute the installation prefix relative to this file.
-get_filename_component(_PROTOBUF_IMPORT_PREFIX
- "${_PROTOBUF_PACKAGE_PREFIX}" PATH)
-get_filename_component(_PROTOBUF_IMPORT_PREFIX
- "${_PROTOBUF_IMPORT_PREFIX}" PATH)
-get_filename_component(_PROTOBUF_IMPORT_PREFIX
- "${_PROTOBUF_IMPORT_PREFIX}" PATH)
-
-# CMake FindProtobuf module compatible file
-if(NOT DEFINED PROTOBUF_MODULE_COMPATIBLE OR "${PROTOBUF_MODULE_COMPATIBLE}")
- include("${_PROTOBUF_PACKAGE_PREFIX}/protobuf-module.cmake")
-endif()
-
-# Cleanup temporary variables.
-set(_PROTOBUF_PACKAGE_PREFIX)
-set(_PROTOBUF_IMPORT_PREFIX)
+# Version info variables
+set(PROTOBUF_VERSION "@protobuf_VERSION@")
+set(PROTOBUF_VERSION_STRING "@protobuf_VERSION_STRING@")
+
+# Current dir
+get_filename_component(_PROTOBUF_PACKAGE_PREFIX
+ "${CMAKE_CURRENT_LIST_FILE}" PATH)
+
+# Imported targets
+include("${_PROTOBUF_PACKAGE_PREFIX}/protobuf-targets.cmake")
+
+# Compute the installation prefix relative to this file.
+get_filename_component(_PROTOBUF_IMPORT_PREFIX
+ "${_PROTOBUF_PACKAGE_PREFIX}" PATH)
+get_filename_component(_PROTOBUF_IMPORT_PREFIX
+ "${_PROTOBUF_IMPORT_PREFIX}" PATH)
+get_filename_component(_PROTOBUF_IMPORT_PREFIX
+ "${_PROTOBUF_IMPORT_PREFIX}" PATH)
+
+# CMake FindProtobuf module compatible file
+if(NOT DEFINED PROTOBUF_MODULE_COMPATIBLE OR "${PROTOBUF_MODULE_COMPATIBLE}")
+ include("${_PROTOBUF_PACKAGE_PREFIX}/protobuf-module.cmake")
+endif()
+
+# Cleanup temporary variables.
+set(_PROTOBUF_PACKAGE_PREFIX)
+set(_PROTOBUF_IMPORT_PREFIX)
diff --git a/cmake/tests.cmake b/cmake/tests.cmake
index 16c94933..65feca21 100644
--- a/cmake/tests.cmake
+++ b/cmake/tests.cmake
@@ -21,6 +21,7 @@ set(lite_test_protos
google/protobuf/unittest_import_lite.proto
google/protobuf/unittest_import_public_lite.proto
google/protobuf/unittest_lite.proto
+ google/protobuf/unittest_no_arena_lite.proto
)
set(tests_protos
@@ -35,11 +36,11 @@ set(tests_protos
google/protobuf/unittest_drop_unknown_fields.proto
google/protobuf/unittest_embed_optimize_for.proto
google/protobuf/unittest_empty.proto
- google/protobuf/unittest_enormous_descriptor.proto
google/protobuf/unittest_import.proto
google/protobuf/unittest_import_public.proto
google/protobuf/unittest_lite_imports_nonlite.proto
google/protobuf/unittest_mset.proto
+ google/protobuf/unittest_mset_wire_format.proto
google/protobuf/unittest_no_arena.proto
google/protobuf/unittest_no_arena_import.proto
google/protobuf/unittest_no_field_presence.proto
@@ -55,6 +56,7 @@ set(tests_protos
google/protobuf/util/internal/testdata/default_value_test.proto
google/protobuf/util/internal/testdata/field_mask.proto
google/protobuf/util/internal/testdata/maps.proto
+ google/protobuf/util/internal/testdata/oneofs.proto
google/protobuf/util/internal/testdata/struct.proto
google/protobuf/util/internal/testdata/timestamp_duration.proto
google/protobuf/util/json_format_proto3.proto
@@ -96,6 +98,12 @@ set(common_test_files
${protobuf_source_dir}/src/google/protobuf/testing/googletest.cc
)
+set(common_lite_test_files
+ ${protobuf_source_dir}/src/google/protobuf/arena_test_util.cc
+ ${protobuf_source_dir}/src/google/protobuf/map_lite_test_util.cc
+ ${protobuf_source_dir}/src/google/protobuf/test_util_lite.cc
+)
+
set(tests_files
${protobuf_source_dir}/src/google/protobuf/any_test.cc
${protobuf_source_dir}/src/google/protobuf/arena_unittest.cc
@@ -134,6 +142,7 @@ set(tests_files
${protobuf_source_dir}/src/google/protobuf/repeated_field_unittest.cc
${protobuf_source_dir}/src/google/protobuf/stubs/bytestream_unittest.cc
${protobuf_source_dir}/src/google/protobuf/stubs/common_unittest.cc
+ ${protobuf_source_dir}/src/google/protobuf/stubs/int128_unittest.cc
${protobuf_source_dir}/src/google/protobuf/stubs/once_unittest.cc
${protobuf_source_dir}/src/google/protobuf/stubs/status_test.cc
${protobuf_source_dir}/src/google/protobuf/stubs/statusor_test.cc
@@ -147,6 +156,7 @@ set(tests_files
${protobuf_source_dir}/src/google/protobuf/text_format_unittest.cc
${protobuf_source_dir}/src/google/protobuf/unknown_field_set_unittest.cc
${protobuf_source_dir}/src/google/protobuf/util/field_comparator_test.cc
+ ${protobuf_source_dir}/src/google/protobuf/util/field_mask_util_test.cc
${protobuf_source_dir}/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
${protobuf_source_dir}/src/google/protobuf/util/internal/json_objectwriter_test.cc
${protobuf_source_dir}/src/google/protobuf/util/internal/json_stream_parser_test.cc
@@ -154,6 +164,7 @@ set(tests_files
${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
${protobuf_source_dir}/src/google/protobuf/util/internal/type_info_test_helper.cc
${protobuf_source_dir}/src/google/protobuf/util/json_util_test.cc
+ ${protobuf_source_dir}/src/google/protobuf/util/time_util_test.cc
${protobuf_source_dir}/src/google/protobuf/util/type_resolver_util_test.cc
${protobuf_source_dir}/src/google/protobuf/well_known_types_unittest.cc
${protobuf_source_dir}/src/google/protobuf/wire_format_unittest.cc
@@ -173,10 +184,13 @@ add_executable(test_plugin ${test_plugin_files})
target_link_libraries(test_plugin libprotoc libprotobuf gmock)
set(lite_test_files
- ${protobuf_source_dir}/src/google/protobuf/arena_test_util.cc
${protobuf_source_dir}/src/google/protobuf/lite_unittest.cc
- ${protobuf_source_dir}/src/google/protobuf/map_lite_test_util.cc
- ${protobuf_source_dir}/src/google/protobuf/test_util_lite.cc
)
-add_executable(lite-test ${lite_test_files} ${lite_test_proto_files})
+add_executable(lite-test ${lite_test_files} ${common_lite_test_files} ${lite_test_proto_files})
target_link_libraries(lite-test libprotobuf-lite)
+
+set(lite_arena_test_files
+ ${protobuf_source_dir}/src/google/protobuf/lite_arena_unittest.cc
+)
+add_executable(lite-arena-test ${lite_arena_test_files} ${common_lite_test_files} ${lite_test_proto_files})
+target_link_libraries(lite-arena-test libprotobuf-lite gmock_main)
diff --git a/configure.ac b/configure.ac
index ef5342ce..0e587893 100644
--- a/configure.ac
+++ b/configure.ac
@@ -12,7 +12,7 @@ AC_PREREQ(2.59)
# In the SVN trunk, the version should always be the next anticipated release
# version with the "-pre" suffix. (We used to use "-SNAPSHOT" but this pushed
# the size of one file name in the dist tarfile over the 99-char limit.)
-AC_INIT([Protocol Buffers],[3.0.0-alpha-4-pre],[protobuf@googlegroups.com],[protobuf])
+AC_INIT([Protocol Buffers],[3.0.0-beta-1],[protobuf@googlegroups.com],[protobuf])
AM_MAINTAINER_MODE([enable])
diff --git a/csharp/README.md b/csharp/README.md
index a798ee62..305c44b6 100644
--- a/csharp/README.md
+++ b/csharp/README.md
@@ -1,7 +1,7 @@
This directory contains the C# Protocol Buffers runtime library.
-Warning: experimental!
-======================
+Status: Alpha - ready for early adopters
+========================================
This code is still under significant churn. Unlike the original port,
it only supports proto3 (but not *all* of proto3 yet) - there are no
@@ -12,15 +12,20 @@ reflection. (It's currently exposed publicly, but won't be
eventually.)
Also unlike the original port, the new version embraces mutability -
-there are no builder types. We plan to add "freezing" operations as
-well as cloning, however.
+there are no builder types.
Usage
=====
-Use `protoc` with the `--csharp_out` option to generate C# files in the specified directory.
-Include these in your C# project, and add a reference to the `Google.Protobuf` project. Currently
-there is no NuGet package for this, but we will be building one as soon as the API is stable.
+The easiest way how to use C# protobufs is via the `Google.Protobuf`
+NuGet package. Just add the NuGet package to your VS project.
+
+Besides C# runtime library, the NuGet package also contains
+precompiled version of `protoc.exe` and a copy of well known `.proto`
+files under the package's `tools` directory.
+
+To generate C# files from your `.proto` files, invoke `protoc` with the
+`--csharp_out` option.
Supported platforms
===================
diff --git a/csharp/generate_protos.sh b/csharp/generate_protos.sh
index 0d217a9d..3a556b0e 100755
--- a/csharp/generate_protos.sh
+++ b/csharp/generate_protos.sh
@@ -35,11 +35,10 @@ if [ -z "$PROTOC" ]; then
fi
fi
-# Descriptor proto
-$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf/Reflection \
- src/google/protobuf/descriptor.proto
-
-$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf/WellKnownTypes \
+# descriptor.proto and well-known types
+$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf \
+ --csharp_opt=base_namespace=Google.Protobuf \
+ src/google/protobuf/descriptor.proto \
src/google/protobuf/any.proto \
src/google/protobuf/api.proto \
src/google/protobuf/duration.proto \
@@ -51,15 +50,18 @@ $PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf/WellKnownTypes \
src/google/protobuf/type.proto \
src/google/protobuf/wrappers.proto
-$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf.Test/TestProtos \
+# Test protos where the namespace matches the target location
+$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf.Test \
+ --csharp_opt=base_namespace=Google.Protobuf \
src/google/protobuf/map_unittest_proto3.proto \
src/google/protobuf/unittest_proto3.proto \
src/google/protobuf/unittest_import_proto3.proto \
src/google/protobuf/unittest_import_public_proto3.proto \
src/google/protobuf/unittest_well_known_types.proto
-
-$PROTOC -Icsharp/protos --csharp_out=csharp/src/Google.Protobuf.Test/TestProtos \
+# Different base namespace to the protos above
+$PROTOC -Icsharp/protos --csharp_out=csharp/src/Google.Protobuf.Test \
+ --csharp_opt=base_namespace=UnitTest.Issues \
csharp/protos/unittest_issues.proto
# AddressBook sample protos
diff --git a/csharp/src/AddressBook/Addressbook.cs b/csharp/src/AddressBook/Addressbook.cs
index f2be5bae..017a3f84 100644
--- a/csharp/src/AddressBook/Addressbook.cs
+++ b/csharp/src/AddressBook/Addressbook.cs
@@ -21,14 +21,14 @@ namespace Google.Protobuf.Examples.AddressBook {
static Addressbook() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "ChFhZGRyZXNzYm9vay5wcm90bxIIdHV0b3JpYWwi1QEKBlBlcnNvbhIMCgRu",
- "YW1lGAEgASgJEgoKAmlkGAIgASgFEg0KBWVtYWlsGAMgASgJEiwKBnBob25l",
- "cxgEIAMoCzIcLnR1dG9yaWFsLlBlcnNvbi5QaG9uZU51bWJlchpHCgtQaG9u",
- "ZU51bWJlchIOCgZudW1iZXIYASABKAkSKAoEdHlwZRgCIAEoDjIaLnR1dG9y",
- "aWFsLlBlcnNvbi5QaG9uZVR5cGUiKwoJUGhvbmVUeXBlEgoKBk1PQklMRRAA",
- "EggKBEhPTUUQARIICgRXT1JLEAIiLwoLQWRkcmVzc0Jvb2sSIAoGcGVvcGxl",
- "GAEgAygLMhAudHV0b3JpYWwuUGVyc29uQlAKFGNvbS5leGFtcGxlLnR1dG9y",
- "aWFsQhFBZGRyZXNzQm9va1Byb3Rvc6oCJEdvb2dsZS5Qcm90b2J1Zi5FeGFt",
+ "ChFhZGRyZXNzYm9vay5wcm90bxIIdHV0b3JpYWwi1QEKBlBlcnNvbhIMCgRu",
+ "YW1lGAEgASgJEgoKAmlkGAIgASgFEg0KBWVtYWlsGAMgASgJEiwKBnBob25l",
+ "cxgEIAMoCzIcLnR1dG9yaWFsLlBlcnNvbi5QaG9uZU51bWJlchpHCgtQaG9u",
+ "ZU51bWJlchIOCgZudW1iZXIYASABKAkSKAoEdHlwZRgCIAEoDjIaLnR1dG9y",
+ "aWFsLlBlcnNvbi5QaG9uZVR5cGUiKwoJUGhvbmVUeXBlEgoKBk1PQklMRRAA",
+ "EggKBEhPTUUQARIICgRXT1JLEAIiLwoLQWRkcmVzc0Jvb2sSIAoGcGVvcGxl",
+ "GAEgAygLMhAudHV0b3JpYWwuUGVyc29uQlAKFGNvbS5leGFtcGxlLnR1dG9y",
+ "aWFsQhFBZGRyZXNzQm9va1Byb3Rvc6oCJEdvb2dsZS5Qcm90b2J1Zi5FeGFt",
"cGxlcy5BZGRyZXNzQm9va2IGcHJvdG8z"));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { },
diff --git a/csharp/src/Google.Protobuf.Conformance/Conformance.cs b/csharp/src/Google.Protobuf.Conformance/Conformance.cs
index e905d4e4..41492f21 100644
--- a/csharp/src/Google.Protobuf.Conformance/Conformance.cs
+++ b/csharp/src/Google.Protobuf.Conformance/Conformance.cs
@@ -21,116 +21,116 @@ namespace Conformance {
static Conformance() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "ChFjb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2UijQEKEkNvbmZvcm1h",
- "bmNlUmVxdWVzdBIaChBwcm90b2J1Zl9wYXlsb2FkGAEgASgMSAASFgoManNv",
- "bl9wYXlsb2FkGAIgASgJSAASOAoXcmVxdWVzdGVkX291dHB1dF9mb3JtYXQY",
- "AyABKA4yFy5jb25mb3JtYW5jZS5XaXJlRm9ybWF0QgkKB3BheWxvYWQilgEK",
- "E0NvbmZvcm1hbmNlUmVzcG9uc2USFQoLcGFyc2VfZXJyb3IYASABKAlIABIX",
- "Cg1ydW50aW1lX2Vycm9yGAIgASgJSAASGgoQcHJvdG9idWZfcGF5bG9hZBgD",
- "IAEoDEgAEhYKDGpzb25fcGF5bG9hZBgEIAEoCUgAEhEKB3NraXBwZWQYBSAB",
- "KAlIAEIICgZyZXN1bHQi6yIKDFRlc3RBbGxUeXBlcxIWCg5vcHRpb25hbF9p",
- "bnQzMhgBIAEoBRIWCg5vcHRpb25hbF9pbnQ2NBgCIAEoAxIXCg9vcHRpb25h",
- "bF91aW50MzIYAyABKA0SFwoPb3B0aW9uYWxfdWludDY0GAQgASgEEhcKD29w",
- "dGlvbmFsX3NpbnQzMhgFIAEoERIXCg9vcHRpb25hbF9zaW50NjQYBiABKBIS",
- "GAoQb3B0aW9uYWxfZml4ZWQzMhgHIAEoBxIYChBvcHRpb25hbF9maXhlZDY0",
- "GAggASgGEhkKEW9wdGlvbmFsX3NmaXhlZDMyGAkgASgPEhkKEW9wdGlvbmFs",
- "X3NmaXhlZDY0GAogASgQEhYKDm9wdGlvbmFsX2Zsb2F0GAsgASgCEhcKD29w",
- "dGlvbmFsX2RvdWJsZRgMIAEoARIVCg1vcHRpb25hbF9ib29sGA0gASgIEhcK",
- "D29wdGlvbmFsX3N0cmluZxgOIAEoCRIWCg5vcHRpb25hbF9ieXRlcxgPIAEo",
- "DBJIChdvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZRgSIAEoCzInLmNvbmZvcm1h",
- "bmNlLlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlEj0KGG9wdGlvbmFsX2Zv",
- "cmVpZ25fbWVzc2FnZRgTIAEoCzIbLmNvbmZvcm1hbmNlLkZvcmVpZ25NZXNz",
- "YWdlEkIKFG9wdGlvbmFsX25lc3RlZF9lbnVtGBUgASgOMiQuY29uZm9ybWFu",
- "Y2UuVGVzdEFsbFR5cGVzLk5lc3RlZEVudW0SNwoVb3B0aW9uYWxfZm9yZWln",
- "bl9lbnVtGBYgASgOMhguY29uZm9ybWFuY2UuRm9yZWlnbkVudW0SIQoVb3B0",
- "aW9uYWxfc3RyaW5nX3BpZWNlGBggASgJQgIIAhIZCg1vcHRpb25hbF9jb3Jk",
- "GBkgASgJQgIIARI0ChFyZWN1cnNpdmVfbWVzc2FnZRgbIAEoCzIZLmNvbmZv",
- "cm1hbmNlLlRlc3RBbGxUeXBlcxIWCg5yZXBlYXRlZF9pbnQzMhgfIAMoBRIW",
- "Cg5yZXBlYXRlZF9pbnQ2NBggIAMoAxIXCg9yZXBlYXRlZF91aW50MzIYISAD",
- "KA0SFwoPcmVwZWF0ZWRfdWludDY0GCIgAygEEhcKD3JlcGVhdGVkX3NpbnQz",
- "MhgjIAMoERIXCg9yZXBlYXRlZF9zaW50NjQYJCADKBISGAoQcmVwZWF0ZWRf",
- "Zml4ZWQzMhglIAMoBxIYChByZXBlYXRlZF9maXhlZDY0GCYgAygGEhkKEXJl",
- "cGVhdGVkX3NmaXhlZDMyGCcgAygPEhkKEXJlcGVhdGVkX3NmaXhlZDY0GCgg",
- "AygQEhYKDnJlcGVhdGVkX2Zsb2F0GCkgAygCEhcKD3JlcGVhdGVkX2RvdWJs",
- "ZRgqIAMoARIVCg1yZXBlYXRlZF9ib29sGCsgAygIEhcKD3JlcGVhdGVkX3N0",
- "cmluZxgsIAMoCRIWCg5yZXBlYXRlZF9ieXRlcxgtIAMoDBJIChdyZXBlYXRl",
- "ZF9uZXN0ZWRfbWVzc2FnZRgwIAMoCzInLmNvbmZvcm1hbmNlLlRlc3RBbGxU",
- "eXBlcy5OZXN0ZWRNZXNzYWdlEj0KGHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2Fn",
- "ZRgxIAMoCzIbLmNvbmZvcm1hbmNlLkZvcmVpZ25NZXNzYWdlEkIKFHJlcGVh",
- "dGVkX25lc3RlZF9lbnVtGDMgAygOMiQuY29uZm9ybWFuY2UuVGVzdEFsbFR5",
- "cGVzLk5lc3RlZEVudW0SNwoVcmVwZWF0ZWRfZm9yZWlnbl9lbnVtGDQgAygO",
- "MhguY29uZm9ybWFuY2UuRm9yZWlnbkVudW0SIQoVcmVwZWF0ZWRfc3RyaW5n",
- "X3BpZWNlGDYgAygJQgIIAhIZCg1yZXBlYXRlZF9jb3JkGDcgAygJQgIIARJF",
- "Cg9tYXBfaW50MzJfaW50MzIYOCADKAsyLC5jb25mb3JtYW5jZS5UZXN0QWxs",
- "VHlwZXMuTWFwSW50MzJJbnQzMkVudHJ5EkUKD21hcF9pbnQ2NF9pbnQ2NBg5",
- "IAMoCzIsLmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBlcy5NYXBJbnQ2NEludDY0",
- "RW50cnkSSQoRbWFwX3VpbnQzMl91aW50MzIYOiADKAsyLi5jb25mb3JtYW5j",
- "ZS5UZXN0QWxsVHlwZXMuTWFwVWludDMyVWludDMyRW50cnkSSQoRbWFwX3Vp",
- "bnQ2NF91aW50NjQYOyADKAsyLi5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMu",
- "TWFwVWludDY0VWludDY0RW50cnkSSQoRbWFwX3NpbnQzMl9zaW50MzIYPCAD",
- "KAsyLi5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwU2ludDMyU2ludDMy",
- "RW50cnkSSQoRbWFwX3NpbnQ2NF9zaW50NjQYPSADKAsyLi5jb25mb3JtYW5j",
- "ZS5UZXN0QWxsVHlwZXMuTWFwU2ludDY0U2ludDY0RW50cnkSTQoTbWFwX2Zp",
- "eGVkMzJfZml4ZWQzMhg+IAMoCzIwLmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBl",
- "cy5NYXBGaXhlZDMyRml4ZWQzMkVudHJ5Ek0KE21hcF9maXhlZDY0X2ZpeGVk",
- "NjQYPyADKAsyMC5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwRml4ZWQ2",
- "NEZpeGVkNjRFbnRyeRJRChVtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIYQCADKAsy",
- "Mi5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwU2ZpeGVkMzJTZml4ZWQz",
- "MkVudHJ5ElEKFW1hcF9zZml4ZWQ2NF9zZml4ZWQ2NBhBIAMoCzIyLmNvbmZv",
- "cm1hbmNlLlRlc3RBbGxUeXBlcy5NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkS",
- "RQoPbWFwX2ludDMyX2Zsb2F0GEIgAygLMiwuY29uZm9ybWFuY2UuVGVzdEFs",
- "bFR5cGVzLk1hcEludDMyRmxvYXRFbnRyeRJHChBtYXBfaW50MzJfZG91Ymxl",
- "GEMgAygLMi0uY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzLk1hcEludDMyRG91",
- "YmxlRW50cnkSQQoNbWFwX2Jvb2xfYm9vbBhEIAMoCzIqLmNvbmZvcm1hbmNl",
- "LlRlc3RBbGxUeXBlcy5NYXBCb29sQm9vbEVudHJ5EkkKEW1hcF9zdHJpbmdf",
- "c3RyaW5nGEUgAygLMi4uY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzLk1hcFN0",
- "cmluZ1N0cmluZ0VudHJ5EkcKEG1hcF9zdHJpbmdfYnl0ZXMYRiADKAsyLS5j",
- "b25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwU3RyaW5nQnl0ZXNFbnRyeRJY",
- "ChltYXBfc3RyaW5nX25lc3RlZF9tZXNzYWdlGEcgAygLMjUuY29uZm9ybWFu",
- "Y2UuVGVzdEFsbFR5cGVzLk1hcFN0cmluZ05lc3RlZE1lc3NhZ2VFbnRyeRJa",
- "ChptYXBfc3RyaW5nX2ZvcmVpZ25fbWVzc2FnZRhIIAMoCzI2LmNvbmZvcm1h",
- "bmNlLlRlc3RBbGxUeXBlcy5NYXBTdHJpbmdGb3JlaWduTWVzc2FnZUVudHJ5",
- "ElIKFm1hcF9zdHJpbmdfbmVzdGVkX2VudW0YSSADKAsyMi5jb25mb3JtYW5j",
- "ZS5UZXN0QWxsVHlwZXMuTWFwU3RyaW5nTmVzdGVkRW51bUVudHJ5ElQKF21h",
- "cF9zdHJpbmdfZm9yZWlnbl9lbnVtGEogAygLMjMuY29uZm9ybWFuY2UuVGVz",
- "dEFsbFR5cGVzLk1hcFN0cmluZ0ZvcmVpZ25FbnVtRW50cnkSFgoMb25lb2Zf",
- "dWludDMyGG8gASgNSAASRwoUb25lb2ZfbmVzdGVkX21lc3NhZ2UYcCABKAsy",
- "Jy5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZUgAEhYK",
- "DG9uZW9mX3N0cmluZxhxIAEoCUgAEhUKC29uZW9mX2J5dGVzGHIgASgMSAAa",
- "SgoNTmVzdGVkTWVzc2FnZRIJCgFhGAEgASgFEi4KC2NvcmVjdXJzaXZlGAIg",
- "ASgLMhkuY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzGjQKEk1hcEludDMySW50",
- "MzJFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAU6AjgBGjQKEk1h",
- "cEludDY0SW50NjRFbnRyeRILCgNrZXkYASABKAMSDQoFdmFsdWUYAiABKAM6",
- "AjgBGjYKFE1hcFVpbnQzMlVpbnQzMkVudHJ5EgsKA2tleRgBIAEoDRINCgV2",
- "YWx1ZRgCIAEoDToCOAEaNgoUTWFwVWludDY0VWludDY0RW50cnkSCwoDa2V5",
- "GAEgASgEEg0KBXZhbHVlGAIgASgEOgI4ARo2ChRNYXBTaW50MzJTaW50MzJF",
- "bnRyeRILCgNrZXkYASABKBESDQoFdmFsdWUYAiABKBE6AjgBGjYKFE1hcFNp",
- "bnQ2NFNpbnQ2NEVudHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1ZRgCIAEoEjoC",
- "OAEaOAoWTWFwRml4ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkYASABKAcSDQoF",
- "dmFsdWUYAiABKAc6AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSCwoD",
- "a2V5GAEgASgGEg0KBXZhbHVlGAIgASgGOgI4ARo6ChhNYXBTZml4ZWQzMlNm",
- "aXhlZDMyRW50cnkSCwoDa2V5GAEgASgPEg0KBXZhbHVlGAIgASgPOgI4ARo6",
- "ChhNYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEgASgQEg0KBXZh",
- "bHVlGAIgASgQOgI4ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkSCwoDa2V5GAEg",
- "ASgFEg0KBXZhbHVlGAIgASgCOgI4ARo1ChNNYXBJbnQzMkRvdWJsZUVudHJ5",
- "EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQTWFwQm9vbEJv",
- "b2xFbnRyeRILCgNrZXkYASABKAgSDQoFdmFsdWUYAiABKAg6AjgBGjYKFE1h",
- "cFN0cmluZ1N0cmluZ0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEo",
- "CToCOAEaNQoTTWFwU3RyaW5nQnl0ZXNFbnRyeRILCgNrZXkYASABKAkSDQoF",
- "dmFsdWUYAiABKAw6AjgBGmYKG01hcFN0cmluZ05lc3RlZE1lc3NhZ2VFbnRy",
- "eRILCgNrZXkYASABKAkSNgoFdmFsdWUYAiABKAsyJy5jb25mb3JtYW5jZS5U",
- "ZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZToCOAEaWwocTWFwU3RyaW5nRm9y",
- "ZWlnbk1lc3NhZ2VFbnRyeRILCgNrZXkYASABKAkSKgoFdmFsdWUYAiABKAsy",
- "Gy5jb25mb3JtYW5jZS5Gb3JlaWduTWVzc2FnZToCOAEaYAoYTWFwU3RyaW5n",
- "TmVzdGVkRW51bUVudHJ5EgsKA2tleRgBIAEoCRIzCgV2YWx1ZRgCIAEoDjIk",
- "LmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBlcy5OZXN0ZWRFbnVtOgI4ARpVChlN",
- "YXBTdHJpbmdGb3JlaWduRW51bUVudHJ5EgsKA2tleRgBIAEoCRInCgV2YWx1",
- "ZRgCIAEoDjIYLmNvbmZvcm1hbmNlLkZvcmVpZ25FbnVtOgI4ASI5CgpOZXN0",
- "ZWRFbnVtEgcKA0ZPTxAAEgcKA0JBUhABEgcKA0JBWhACEhAKA05FRxD/////",
- "//////8BQg0KC29uZW9mX2ZpZWxkIhsKDkZvcmVpZ25NZXNzYWdlEgkKAWMY",
- "ASABKAUqNQoKV2lyZUZvcm1hdBIPCgtVTlNQRUNJRklFRBAAEgwKCFBST1RP",
- "QlVGEAESCAoESlNPThACKkAKC0ZvcmVpZ25FbnVtEg8KC0ZPUkVJR05fRk9P",
- "EAASDwoLRk9SRUlHTl9CQVIQARIPCgtGT1JFSUdOX0JBWhACQiEKH2NvbS5n",
+ "ChFjb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2UijQEKEkNvbmZvcm1h",
+ "bmNlUmVxdWVzdBIaChBwcm90b2J1Zl9wYXlsb2FkGAEgASgMSAASFgoManNv",
+ "bl9wYXlsb2FkGAIgASgJSAASOAoXcmVxdWVzdGVkX291dHB1dF9mb3JtYXQY",
+ "AyABKA4yFy5jb25mb3JtYW5jZS5XaXJlRm9ybWF0QgkKB3BheWxvYWQilgEK",
+ "E0NvbmZvcm1hbmNlUmVzcG9uc2USFQoLcGFyc2VfZXJyb3IYASABKAlIABIX",
+ "Cg1ydW50aW1lX2Vycm9yGAIgASgJSAASGgoQcHJvdG9idWZfcGF5bG9hZBgD",
+ "IAEoDEgAEhYKDGpzb25fcGF5bG9hZBgEIAEoCUgAEhEKB3NraXBwZWQYBSAB",
+ "KAlIAEIICgZyZXN1bHQi6yIKDFRlc3RBbGxUeXBlcxIWCg5vcHRpb25hbF9p",
+ "bnQzMhgBIAEoBRIWCg5vcHRpb25hbF9pbnQ2NBgCIAEoAxIXCg9vcHRpb25h",
+ "bF91aW50MzIYAyABKA0SFwoPb3B0aW9uYWxfdWludDY0GAQgASgEEhcKD29w",
+ "dGlvbmFsX3NpbnQzMhgFIAEoERIXCg9vcHRpb25hbF9zaW50NjQYBiABKBIS",
+ "GAoQb3B0aW9uYWxfZml4ZWQzMhgHIAEoBxIYChBvcHRpb25hbF9maXhlZDY0",
+ "GAggASgGEhkKEW9wdGlvbmFsX3NmaXhlZDMyGAkgASgPEhkKEW9wdGlvbmFs",
+ "X3NmaXhlZDY0GAogASgQEhYKDm9wdGlvbmFsX2Zsb2F0GAsgASgCEhcKD29w",
+ "dGlvbmFsX2RvdWJsZRgMIAEoARIVCg1vcHRpb25hbF9ib29sGA0gASgIEhcK",
+ "D29wdGlvbmFsX3N0cmluZxgOIAEoCRIWCg5vcHRpb25hbF9ieXRlcxgPIAEo",
+ "DBJIChdvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZRgSIAEoCzInLmNvbmZvcm1h",
+ "bmNlLlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlEj0KGG9wdGlvbmFsX2Zv",
+ "cmVpZ25fbWVzc2FnZRgTIAEoCzIbLmNvbmZvcm1hbmNlLkZvcmVpZ25NZXNz",
+ "YWdlEkIKFG9wdGlvbmFsX25lc3RlZF9lbnVtGBUgASgOMiQuY29uZm9ybWFu",
+ "Y2UuVGVzdEFsbFR5cGVzLk5lc3RlZEVudW0SNwoVb3B0aW9uYWxfZm9yZWln",
+ "bl9lbnVtGBYgASgOMhguY29uZm9ybWFuY2UuRm9yZWlnbkVudW0SIQoVb3B0",
+ "aW9uYWxfc3RyaW5nX3BpZWNlGBggASgJQgIIAhIZCg1vcHRpb25hbF9jb3Jk",
+ "GBkgASgJQgIIARI0ChFyZWN1cnNpdmVfbWVzc2FnZRgbIAEoCzIZLmNvbmZv",
+ "cm1hbmNlLlRlc3RBbGxUeXBlcxIWCg5yZXBlYXRlZF9pbnQzMhgfIAMoBRIW",
+ "Cg5yZXBlYXRlZF9pbnQ2NBggIAMoAxIXCg9yZXBlYXRlZF91aW50MzIYISAD",
+ "KA0SFwoPcmVwZWF0ZWRfdWludDY0GCIgAygEEhcKD3JlcGVhdGVkX3NpbnQz",
+ "MhgjIAMoERIXCg9yZXBlYXRlZF9zaW50NjQYJCADKBISGAoQcmVwZWF0ZWRf",
+ "Zml4ZWQzMhglIAMoBxIYChByZXBlYXRlZF9maXhlZDY0GCYgAygGEhkKEXJl",
+ "cGVhdGVkX3NmaXhlZDMyGCcgAygPEhkKEXJlcGVhdGVkX3NmaXhlZDY0GCgg",
+ "AygQEhYKDnJlcGVhdGVkX2Zsb2F0GCkgAygCEhcKD3JlcGVhdGVkX2RvdWJs",
+ "ZRgqIAMoARIVCg1yZXBlYXRlZF9ib29sGCsgAygIEhcKD3JlcGVhdGVkX3N0",
+ "cmluZxgsIAMoCRIWCg5yZXBlYXRlZF9ieXRlcxgtIAMoDBJIChdyZXBlYXRl",
+ "ZF9uZXN0ZWRfbWVzc2FnZRgwIAMoCzInLmNvbmZvcm1hbmNlLlRlc3RBbGxU",
+ "eXBlcy5OZXN0ZWRNZXNzYWdlEj0KGHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2Fn",
+ "ZRgxIAMoCzIbLmNvbmZvcm1hbmNlLkZvcmVpZ25NZXNzYWdlEkIKFHJlcGVh",
+ "dGVkX25lc3RlZF9lbnVtGDMgAygOMiQuY29uZm9ybWFuY2UuVGVzdEFsbFR5",
+ "cGVzLk5lc3RlZEVudW0SNwoVcmVwZWF0ZWRfZm9yZWlnbl9lbnVtGDQgAygO",
+ "MhguY29uZm9ybWFuY2UuRm9yZWlnbkVudW0SIQoVcmVwZWF0ZWRfc3RyaW5n",
+ "X3BpZWNlGDYgAygJQgIIAhIZCg1yZXBlYXRlZF9jb3JkGDcgAygJQgIIARJF",
+ "Cg9tYXBfaW50MzJfaW50MzIYOCADKAsyLC5jb25mb3JtYW5jZS5UZXN0QWxs",
+ "VHlwZXMuTWFwSW50MzJJbnQzMkVudHJ5EkUKD21hcF9pbnQ2NF9pbnQ2NBg5",
+ "IAMoCzIsLmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBlcy5NYXBJbnQ2NEludDY0",
+ "RW50cnkSSQoRbWFwX3VpbnQzMl91aW50MzIYOiADKAsyLi5jb25mb3JtYW5j",
+ "ZS5UZXN0QWxsVHlwZXMuTWFwVWludDMyVWludDMyRW50cnkSSQoRbWFwX3Vp",
+ "bnQ2NF91aW50NjQYOyADKAsyLi5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMu",
+ "TWFwVWludDY0VWludDY0RW50cnkSSQoRbWFwX3NpbnQzMl9zaW50MzIYPCAD",
+ "KAsyLi5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwU2ludDMyU2ludDMy",
+ "RW50cnkSSQoRbWFwX3NpbnQ2NF9zaW50NjQYPSADKAsyLi5jb25mb3JtYW5j",
+ "ZS5UZXN0QWxsVHlwZXMuTWFwU2ludDY0U2ludDY0RW50cnkSTQoTbWFwX2Zp",
+ "eGVkMzJfZml4ZWQzMhg+IAMoCzIwLmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBl",
+ "cy5NYXBGaXhlZDMyRml4ZWQzMkVudHJ5Ek0KE21hcF9maXhlZDY0X2ZpeGVk",
+ "NjQYPyADKAsyMC5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwRml4ZWQ2",
+ "NEZpeGVkNjRFbnRyeRJRChVtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIYQCADKAsy",
+ "Mi5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwU2ZpeGVkMzJTZml4ZWQz",
+ "MkVudHJ5ElEKFW1hcF9zZml4ZWQ2NF9zZml4ZWQ2NBhBIAMoCzIyLmNvbmZv",
+ "cm1hbmNlLlRlc3RBbGxUeXBlcy5NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkS",
+ "RQoPbWFwX2ludDMyX2Zsb2F0GEIgAygLMiwuY29uZm9ybWFuY2UuVGVzdEFs",
+ "bFR5cGVzLk1hcEludDMyRmxvYXRFbnRyeRJHChBtYXBfaW50MzJfZG91Ymxl",
+ "GEMgAygLMi0uY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzLk1hcEludDMyRG91",
+ "YmxlRW50cnkSQQoNbWFwX2Jvb2xfYm9vbBhEIAMoCzIqLmNvbmZvcm1hbmNl",
+ "LlRlc3RBbGxUeXBlcy5NYXBCb29sQm9vbEVudHJ5EkkKEW1hcF9zdHJpbmdf",
+ "c3RyaW5nGEUgAygLMi4uY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzLk1hcFN0",
+ "cmluZ1N0cmluZ0VudHJ5EkcKEG1hcF9zdHJpbmdfYnl0ZXMYRiADKAsyLS5j",
+ "b25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwU3RyaW5nQnl0ZXNFbnRyeRJY",
+ "ChltYXBfc3RyaW5nX25lc3RlZF9tZXNzYWdlGEcgAygLMjUuY29uZm9ybWFu",
+ "Y2UuVGVzdEFsbFR5cGVzLk1hcFN0cmluZ05lc3RlZE1lc3NhZ2VFbnRyeRJa",
+ "ChptYXBfc3RyaW5nX2ZvcmVpZ25fbWVzc2FnZRhIIAMoCzI2LmNvbmZvcm1h",
+ "bmNlLlRlc3RBbGxUeXBlcy5NYXBTdHJpbmdGb3JlaWduTWVzc2FnZUVudHJ5",
+ "ElIKFm1hcF9zdHJpbmdfbmVzdGVkX2VudW0YSSADKAsyMi5jb25mb3JtYW5j",
+ "ZS5UZXN0QWxsVHlwZXMuTWFwU3RyaW5nTmVzdGVkRW51bUVudHJ5ElQKF21h",
+ "cF9zdHJpbmdfZm9yZWlnbl9lbnVtGEogAygLMjMuY29uZm9ybWFuY2UuVGVz",
+ "dEFsbFR5cGVzLk1hcFN0cmluZ0ZvcmVpZ25FbnVtRW50cnkSFgoMb25lb2Zf",
+ "dWludDMyGG8gASgNSAASRwoUb25lb2ZfbmVzdGVkX21lc3NhZ2UYcCABKAsy",
+ "Jy5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZUgAEhYK",
+ "DG9uZW9mX3N0cmluZxhxIAEoCUgAEhUKC29uZW9mX2J5dGVzGHIgASgMSAAa",
+ "SgoNTmVzdGVkTWVzc2FnZRIJCgFhGAEgASgFEi4KC2NvcmVjdXJzaXZlGAIg",
+ "ASgLMhkuY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzGjQKEk1hcEludDMySW50",
+ "MzJFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAU6AjgBGjQKEk1h",
+ "cEludDY0SW50NjRFbnRyeRILCgNrZXkYASABKAMSDQoFdmFsdWUYAiABKAM6",
+ "AjgBGjYKFE1hcFVpbnQzMlVpbnQzMkVudHJ5EgsKA2tleRgBIAEoDRINCgV2",
+ "YWx1ZRgCIAEoDToCOAEaNgoUTWFwVWludDY0VWludDY0RW50cnkSCwoDa2V5",
+ "GAEgASgEEg0KBXZhbHVlGAIgASgEOgI4ARo2ChRNYXBTaW50MzJTaW50MzJF",
+ "bnRyeRILCgNrZXkYASABKBESDQoFdmFsdWUYAiABKBE6AjgBGjYKFE1hcFNp",
+ "bnQ2NFNpbnQ2NEVudHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1ZRgCIAEoEjoC",
+ "OAEaOAoWTWFwRml4ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkYASABKAcSDQoF",
+ "dmFsdWUYAiABKAc6AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSCwoD",
+ "a2V5GAEgASgGEg0KBXZhbHVlGAIgASgGOgI4ARo6ChhNYXBTZml4ZWQzMlNm",
+ "aXhlZDMyRW50cnkSCwoDa2V5GAEgASgPEg0KBXZhbHVlGAIgASgPOgI4ARo6",
+ "ChhNYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEgASgQEg0KBXZh",
+ "bHVlGAIgASgQOgI4ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkSCwoDa2V5GAEg",
+ "ASgFEg0KBXZhbHVlGAIgASgCOgI4ARo1ChNNYXBJbnQzMkRvdWJsZUVudHJ5",
+ "EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQTWFwQm9vbEJv",
+ "b2xFbnRyeRILCgNrZXkYASABKAgSDQoFdmFsdWUYAiABKAg6AjgBGjYKFE1h",
+ "cFN0cmluZ1N0cmluZ0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEo",
+ "CToCOAEaNQoTTWFwU3RyaW5nQnl0ZXNFbnRyeRILCgNrZXkYASABKAkSDQoF",
+ "dmFsdWUYAiABKAw6AjgBGmYKG01hcFN0cmluZ05lc3RlZE1lc3NhZ2VFbnRy",
+ "eRILCgNrZXkYASABKAkSNgoFdmFsdWUYAiABKAsyJy5jb25mb3JtYW5jZS5U",
+ "ZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZToCOAEaWwocTWFwU3RyaW5nRm9y",
+ "ZWlnbk1lc3NhZ2VFbnRyeRILCgNrZXkYASABKAkSKgoFdmFsdWUYAiABKAsy",
+ "Gy5jb25mb3JtYW5jZS5Gb3JlaWduTWVzc2FnZToCOAEaYAoYTWFwU3RyaW5n",
+ "TmVzdGVkRW51bUVudHJ5EgsKA2tleRgBIAEoCRIzCgV2YWx1ZRgCIAEoDjIk",
+ "LmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBlcy5OZXN0ZWRFbnVtOgI4ARpVChlN",
+ "YXBTdHJpbmdGb3JlaWduRW51bUVudHJ5EgsKA2tleRgBIAEoCRInCgV2YWx1",
+ "ZRgCIAEoDjIYLmNvbmZvcm1hbmNlLkZvcmVpZ25FbnVtOgI4ASI5CgpOZXN0",
+ "ZWRFbnVtEgcKA0ZPTxAAEgcKA0JBUhABEgcKA0JBWhACEhAKA05FRxD/////",
+ "//////8BQg0KC29uZW9mX2ZpZWxkIhsKDkZvcmVpZ25NZXNzYWdlEgkKAWMY",
+ "ASABKAUqNQoKV2lyZUZvcm1hdBIPCgtVTlNQRUNJRklFRBAAEgwKCFBST1RP",
+ "QlVGEAESCAoESlNPThACKkAKC0ZvcmVpZ25FbnVtEg8KC0ZPUkVJR05fRk9P",
+ "EAASDwoLRk9SRUlHTl9CQVIQARIPCgtGT1JFSUdOX0JBWhACQiEKH2NvbS5n",
"b29nbGUucHJvdG9idWYuY29uZm9ybWFuY2ViBnByb3RvMw=="));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { },
diff --git a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
index d9593828..33be5dae 100644
--- a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
+++ b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
@@ -109,6 +109,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestCornerCases.cs" />
<Compile Include="TestProtos\UnittestWellKnownTypes.cs" />
+ <Compile Include="WellKnownTypes\AnyTest.cs" />
<Compile Include="WellKnownTypes\DurationTest.cs" />
<Compile Include="WellKnownTypes\TimestampTest.cs" />
<Compile Include="WellKnownTypes\WrappersTest.cs" />
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs
index e9e18193..179afda9 100644
--- a/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs
+++ b/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs
@@ -21,129 +21,129 @@ namespace Google.Protobuf.TestProtos {
static MapUnittestProto3() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "Cilnb29nbGUvcHJvdG9idWYvbWFwX3VuaXR0ZXN0X3Byb3RvMy5wcm90bxIR",
- "cHJvdG9idWZfdW5pdHRlc3QaJWdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9w",
- "cm90bzMucHJvdG8ilhIKB1Rlc3RNYXASRgoPbWFwX2ludDMyX2ludDMyGAEg",
- "AygLMi0ucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBJbnQzMkludDMy",
- "RW50cnkSRgoPbWFwX2ludDY0X2ludDY0GAIgAygLMi0ucHJvdG9idWZfdW5p",
- "dHRlc3QuVGVzdE1hcC5NYXBJbnQ2NEludDY0RW50cnkSSgoRbWFwX3VpbnQz",
- "Ml91aW50MzIYAyADKAsyLy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1h",
- "cFVpbnQzMlVpbnQzMkVudHJ5EkoKEW1hcF91aW50NjRfdWludDY0GAQgAygL",
- "Mi8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBVaW50NjRVaW50NjRF",
- "bnRyeRJKChFtYXBfc2ludDMyX3NpbnQzMhgFIAMoCzIvLnByb3RvYnVmX3Vu",
- "aXR0ZXN0LlRlc3RNYXAuTWFwU2ludDMyU2ludDMyRW50cnkSSgoRbWFwX3Np",
- "bnQ2NF9zaW50NjQYBiADKAsyLy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFw",
- "Lk1hcFNpbnQ2NFNpbnQ2NEVudHJ5Ek4KE21hcF9maXhlZDMyX2ZpeGVkMzIY",
- "ByADKAsyMS5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1hcEZpeGVkMzJG",
- "aXhlZDMyRW50cnkSTgoTbWFwX2ZpeGVkNjRfZml4ZWQ2NBgIIAMoCzIxLnBy",
- "b3RvYnVmX3VuaXR0ZXN0LlRlc3RNYXAuTWFwRml4ZWQ2NEZpeGVkNjRFbnRy",
- "eRJSChVtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIYCSADKAsyMy5wcm90b2J1Zl91",
- "bml0dGVzdC5UZXN0TWFwLk1hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeRJSChVt",
- "YXBfc2ZpeGVkNjRfc2ZpeGVkNjQYCiADKAsyMy5wcm90b2J1Zl91bml0dGVz",
- "dC5UZXN0TWFwLk1hcFNmaXhlZDY0U2ZpeGVkNjRFbnRyeRJGCg9tYXBfaW50",
- "MzJfZmxvYXQYCyADKAsyLS5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1h",
- "cEludDMyRmxvYXRFbnRyeRJIChBtYXBfaW50MzJfZG91YmxlGAwgAygLMi4u",
- "cHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBJbnQzMkRvdWJsZUVudHJ5",
- "EkIKDW1hcF9ib29sX2Jvb2wYDSADKAsyKy5wcm90b2J1Zl91bml0dGVzdC5U",
- "ZXN0TWFwLk1hcEJvb2xCb29sRW50cnkSSgoRbWFwX3N0cmluZ19zdHJpbmcY",
- "DiADKAsyLy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1hcFN0cmluZ1N0",
- "cmluZ0VudHJ5EkYKD21hcF9pbnQzMl9ieXRlcxgPIAMoCzItLnByb3RvYnVm",
- "X3VuaXR0ZXN0LlRlc3RNYXAuTWFwSW50MzJCeXRlc0VudHJ5EkQKDm1hcF9p",
- "bnQzMl9lbnVtGBAgAygLMiwucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5N",
- "YXBJbnQzMkVudW1FbnRyeRJZChltYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdl",
- "GBEgAygLMjYucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBJbnQzMkZv",
- "cmVpZ25NZXNzYWdlRW50cnkaNAoSTWFwSW50MzJJbnQzMkVudHJ5EgsKA2tl",
- "eRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEaNAoSTWFwSW50NjRJbnQ2NEVu",
- "dHJ5EgsKA2tleRgBIAEoAxINCgV2YWx1ZRgCIAEoAzoCOAEaNgoUTWFwVWlu",
- "dDMyVWludDMyRW50cnkSCwoDa2V5GAEgASgNEg0KBXZhbHVlGAIgASgNOgI4",
- "ARo2ChRNYXBVaW50NjRVaW50NjRFbnRyeRILCgNrZXkYASABKAQSDQoFdmFs",
- "dWUYAiABKAQ6AjgBGjYKFE1hcFNpbnQzMlNpbnQzMkVudHJ5EgsKA2tleRgB",
- "IAEoERINCgV2YWx1ZRgCIAEoEToCOAEaNgoUTWFwU2ludDY0U2ludDY0RW50",
- "cnkSCwoDa2V5GAEgASgSEg0KBXZhbHVlGAIgASgSOgI4ARo4ChZNYXBGaXhl",
- "ZDMyRml4ZWQzMkVudHJ5EgsKA2tleRgBIAEoBxINCgV2YWx1ZRgCIAEoBzoC",
- "OAEaOAoWTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeRILCgNrZXkYASABKAYSDQoF",
- "dmFsdWUYAiABKAY6AjgBGjoKGE1hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeRIL",
- "CgNrZXkYASABKA8SDQoFdmFsdWUYAiABKA86AjgBGjoKGE1hcFNmaXhlZDY0",
- "U2ZpeGVkNjRFbnRyeRILCgNrZXkYASABKBASDQoFdmFsdWUYAiABKBA6AjgB",
- "GjQKEk1hcEludDMyRmxvYXRFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUY",
- "AiABKAI6AjgBGjUKE01hcEludDMyRG91YmxlRW50cnkSCwoDa2V5GAEgASgF",
- "Eg0KBXZhbHVlGAIgASgBOgI4ARoyChBNYXBCb29sQm9vbEVudHJ5EgsKA2tl",
- "eRgBIAEoCBINCgV2YWx1ZRgCIAEoCDoCOAEaNgoUTWFwU3RyaW5nU3RyaW5n",
- "RW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ARo0ChJNYXBJ",
- "bnQzMkJ5dGVzRW50cnkSCwoDa2V5GAEgASgFEg0KBXZhbHVlGAIgASgMOgI4",
- "ARpPChFNYXBJbnQzMkVudW1FbnRyeRILCgNrZXkYASABKAUSKQoFdmFsdWUY",
- "AiABKA4yGi5wcm90b2J1Zl91bml0dGVzdC5NYXBFbnVtOgI4ARpgChtNYXBJ",
- "bnQzMkZvcmVpZ25NZXNzYWdlRW50cnkSCwoDa2V5GAEgASgFEjAKBXZhbHVl",
- "GAIgASgLMiEucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2U6AjgB",
- "IkEKEVRlc3RNYXBTdWJtZXNzYWdlEiwKCHRlc3RfbWFwGAEgASgLMhoucHJv",
- "dG9idWZfdW5pdHRlc3QuVGVzdE1hcCK8AQoOVGVzdE1lc3NhZ2VNYXASUQoR",
- "bWFwX2ludDMyX21lc3NhZ2UYASADKAsyNi5wcm90b2J1Zl91bml0dGVzdC5U",
- "ZXN0TWVzc2FnZU1hcC5NYXBJbnQzMk1lc3NhZ2VFbnRyeRpXChRNYXBJbnQz",
- "Mk1lc3NhZ2VFbnRyeRILCgNrZXkYASABKAUSLgoFdmFsdWUYAiABKAsyHy5w",
- "cm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXM6AjgBIuMBCg9UZXN0U2Ft",
- "ZVR5cGVNYXASOgoEbWFwMRgBIAMoCzIsLnByb3RvYnVmX3VuaXR0ZXN0LlRl",
- "c3RTYW1lVHlwZU1hcC5NYXAxRW50cnkSOgoEbWFwMhgCIAMoCzIsLnByb3Rv",
- "YnVmX3VuaXR0ZXN0LlRlc3RTYW1lVHlwZU1hcC5NYXAyRW50cnkaKwoJTWFw",
- "MUVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEaKwoJTWFw",
- "MkVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEi5BAKDFRl",
- "c3RBcmVuYU1hcBJLCg9tYXBfaW50MzJfaW50MzIYASADKAsyMi5wcm90b2J1",
- "Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwSW50MzJJbnQzMkVudHJ5EksK",
- "D21hcF9pbnQ2NF9pbnQ2NBgCIAMoCzIyLnByb3RvYnVmX3VuaXR0ZXN0LlRl",
- "c3RBcmVuYU1hcC5NYXBJbnQ2NEludDY0RW50cnkSTwoRbWFwX3VpbnQzMl91",
- "aW50MzIYAyADKAsyNC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAu",
- "TWFwVWludDMyVWludDMyRW50cnkSTwoRbWFwX3VpbnQ2NF91aW50NjQYBCAD",
- "KAsyNC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwVWludDY0",
- "VWludDY0RW50cnkSTwoRbWFwX3NpbnQzMl9zaW50MzIYBSADKAsyNC5wcm90",
- "b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwU2ludDMyU2ludDMyRW50",
- "cnkSTwoRbWFwX3NpbnQ2NF9zaW50NjQYBiADKAsyNC5wcm90b2J1Zl91bml0",
- "dGVzdC5UZXN0QXJlbmFNYXAuTWFwU2ludDY0U2ludDY0RW50cnkSUwoTbWFw",
- "X2ZpeGVkMzJfZml4ZWQzMhgHIAMoCzI2LnByb3RvYnVmX3VuaXR0ZXN0LlRl",
- "c3RBcmVuYU1hcC5NYXBGaXhlZDMyRml4ZWQzMkVudHJ5ElMKE21hcF9maXhl",
- "ZDY0X2ZpeGVkNjQYCCADKAsyNi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJl",
- "bmFNYXAuTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeRJXChVtYXBfc2ZpeGVkMzJf",
- "c2ZpeGVkMzIYCSADKAsyOC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFN",
- "YXAuTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5ElcKFW1hcF9zZml4ZWQ2NF9z",
- "Zml4ZWQ2NBgKIAMoCzI4LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBcmVuYU1h",
- "cC5NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkSSwoPbWFwX2ludDMyX2Zsb2F0",
- "GAsgAygLMjIucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwLk1hcElu",
- "dDMyRmxvYXRFbnRyeRJNChBtYXBfaW50MzJfZG91YmxlGAwgAygLMjMucHJv",
- "dG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwLk1hcEludDMyRG91YmxlRW50",
- "cnkSRwoNbWFwX2Jvb2xfYm9vbBgNIAMoCzIwLnByb3RvYnVmX3VuaXR0ZXN0",
- "LlRlc3RBcmVuYU1hcC5NYXBCb29sQm9vbEVudHJ5EkkKDm1hcF9pbnQzMl9l",
- "bnVtGA4gAygLMjEucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwLk1h",
- "cEludDMyRW51bUVudHJ5El4KGW1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UY",
- "DyADKAsyOy5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwSW50",
- "MzJGb3JlaWduTWVzc2FnZUVudHJ5GjQKEk1hcEludDMySW50MzJFbnRyeRIL",
- "CgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAU6AjgBGjQKEk1hcEludDY0SW50",
- "NjRFbnRyeRILCgNrZXkYASABKAMSDQoFdmFsdWUYAiABKAM6AjgBGjYKFE1h",
- "cFVpbnQzMlVpbnQzMkVudHJ5EgsKA2tleRgBIAEoDRINCgV2YWx1ZRgCIAEo",
- "DToCOAEaNgoUTWFwVWludDY0VWludDY0RW50cnkSCwoDa2V5GAEgASgEEg0K",
- "BXZhbHVlGAIgASgEOgI4ARo2ChRNYXBTaW50MzJTaW50MzJFbnRyeRILCgNr",
- "ZXkYASABKBESDQoFdmFsdWUYAiABKBE6AjgBGjYKFE1hcFNpbnQ2NFNpbnQ2",
- "NEVudHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1ZRgCIAEoEjoCOAEaOAoWTWFw",
- "Rml4ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkYASABKAcSDQoFdmFsdWUYAiAB",
- "KAc6AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSCwoDa2V5GAEgASgG",
- "Eg0KBXZhbHVlGAIgASgGOgI4ARo6ChhNYXBTZml4ZWQzMlNmaXhlZDMyRW50",
- "cnkSCwoDa2V5GAEgASgPEg0KBXZhbHVlGAIgASgPOgI4ARo6ChhNYXBTZml4",
- "ZWQ2NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEgASgQEg0KBXZhbHVlGAIgASgQ",
- "OgI4ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkSCwoDa2V5GAEgASgFEg0KBXZh",
- "bHVlGAIgASgCOgI4ARo1ChNNYXBJbnQzMkRvdWJsZUVudHJ5EgsKA2tleRgB",
- "IAEoBRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQTWFwQm9vbEJvb2xFbnRyeRIL",
- "CgNrZXkYASABKAgSDQoFdmFsdWUYAiABKAg6AjgBGk8KEU1hcEludDMyRW51",
- "bUVudHJ5EgsKA2tleRgBIAEoBRIpCgV2YWx1ZRgCIAEoDjIaLnByb3RvYnVm",
- "X3VuaXR0ZXN0Lk1hcEVudW06AjgBGmAKG01hcEludDMyRm9yZWlnbk1lc3Nh",
- "Z2VFbnRyeRILCgNrZXkYASABKAUSMAoFdmFsdWUYAiABKAsyIS5wcm90b2J1",
- "Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZToCOAEi5AEKH01lc3NhZ2VDb250",
- "YWluaW5nRW51bUNhbGxlZFR5cGUSSgoEdHlwZRgBIAMoCzI8LnByb3RvYnVm",
- "X3VuaXR0ZXN0Lk1lc3NhZ2VDb250YWluaW5nRW51bUNhbGxlZFR5cGUuVHlw",
- "ZUVudHJ5Gl8KCVR5cGVFbnRyeRILCgNrZXkYASABKAUSQQoFdmFsdWUYAiAB",
- "KAsyMi5wcm90b2J1Zl91bml0dGVzdC5NZXNzYWdlQ29udGFpbmluZ0VudW1D",
- "YWxsZWRUeXBlOgI4ASIUCgRUeXBlEgwKCFRZUEVfRk9PEAAinQEKH01lc3Nh",
- "Z2VDb250YWluaW5nTWFwQ2FsbGVkRW50cnkSTAoFZW50cnkYASADKAsyPS5w",
- "cm90b2J1Zl91bml0dGVzdC5NZXNzYWdlQ29udGFpbmluZ01hcENhbGxlZEVu",
- "dHJ5LkVudHJ5RW50cnkaLAoKRW50cnlFbnRyeRILCgNrZXkYASABKAUSDQoF",
- "dmFsdWUYAiABKAU6AjgBKj8KB01hcEVudW0SEAoMTUFQX0VOVU1fRk9PEAAS",
- "EAoMTUFQX0VOVU1fQkFSEAESEAoMTUFQX0VOVU1fQkFaEAJCIPgBAaoCGkdv",
+ "Cilnb29nbGUvcHJvdG9idWYvbWFwX3VuaXR0ZXN0X3Byb3RvMy5wcm90bxIR",
+ "cHJvdG9idWZfdW5pdHRlc3QaJWdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9w",
+ "cm90bzMucHJvdG8ilhIKB1Rlc3RNYXASRgoPbWFwX2ludDMyX2ludDMyGAEg",
+ "AygLMi0ucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBJbnQzMkludDMy",
+ "RW50cnkSRgoPbWFwX2ludDY0X2ludDY0GAIgAygLMi0ucHJvdG9idWZfdW5p",
+ "dHRlc3QuVGVzdE1hcC5NYXBJbnQ2NEludDY0RW50cnkSSgoRbWFwX3VpbnQz",
+ "Ml91aW50MzIYAyADKAsyLy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1h",
+ "cFVpbnQzMlVpbnQzMkVudHJ5EkoKEW1hcF91aW50NjRfdWludDY0GAQgAygL",
+ "Mi8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBVaW50NjRVaW50NjRF",
+ "bnRyeRJKChFtYXBfc2ludDMyX3NpbnQzMhgFIAMoCzIvLnByb3RvYnVmX3Vu",
+ "aXR0ZXN0LlRlc3RNYXAuTWFwU2ludDMyU2ludDMyRW50cnkSSgoRbWFwX3Np",
+ "bnQ2NF9zaW50NjQYBiADKAsyLy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFw",
+ "Lk1hcFNpbnQ2NFNpbnQ2NEVudHJ5Ek4KE21hcF9maXhlZDMyX2ZpeGVkMzIY",
+ "ByADKAsyMS5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1hcEZpeGVkMzJG",
+ "aXhlZDMyRW50cnkSTgoTbWFwX2ZpeGVkNjRfZml4ZWQ2NBgIIAMoCzIxLnBy",
+ "b3RvYnVmX3VuaXR0ZXN0LlRlc3RNYXAuTWFwRml4ZWQ2NEZpeGVkNjRFbnRy",
+ "eRJSChVtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIYCSADKAsyMy5wcm90b2J1Zl91",
+ "bml0dGVzdC5UZXN0TWFwLk1hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeRJSChVt",
+ "YXBfc2ZpeGVkNjRfc2ZpeGVkNjQYCiADKAsyMy5wcm90b2J1Zl91bml0dGVz",
+ "dC5UZXN0TWFwLk1hcFNmaXhlZDY0U2ZpeGVkNjRFbnRyeRJGCg9tYXBfaW50",
+ "MzJfZmxvYXQYCyADKAsyLS5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1h",
+ "cEludDMyRmxvYXRFbnRyeRJIChBtYXBfaW50MzJfZG91YmxlGAwgAygLMi4u",
+ "cHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBJbnQzMkRvdWJsZUVudHJ5",
+ "EkIKDW1hcF9ib29sX2Jvb2wYDSADKAsyKy5wcm90b2J1Zl91bml0dGVzdC5U",
+ "ZXN0TWFwLk1hcEJvb2xCb29sRW50cnkSSgoRbWFwX3N0cmluZ19zdHJpbmcY",
+ "DiADKAsyLy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1hcFN0cmluZ1N0",
+ "cmluZ0VudHJ5EkYKD21hcF9pbnQzMl9ieXRlcxgPIAMoCzItLnByb3RvYnVm",
+ "X3VuaXR0ZXN0LlRlc3RNYXAuTWFwSW50MzJCeXRlc0VudHJ5EkQKDm1hcF9p",
+ "bnQzMl9lbnVtGBAgAygLMiwucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5N",
+ "YXBJbnQzMkVudW1FbnRyeRJZChltYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdl",
+ "GBEgAygLMjYucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBJbnQzMkZv",
+ "cmVpZ25NZXNzYWdlRW50cnkaNAoSTWFwSW50MzJJbnQzMkVudHJ5EgsKA2tl",
+ "eRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEaNAoSTWFwSW50NjRJbnQ2NEVu",
+ "dHJ5EgsKA2tleRgBIAEoAxINCgV2YWx1ZRgCIAEoAzoCOAEaNgoUTWFwVWlu",
+ "dDMyVWludDMyRW50cnkSCwoDa2V5GAEgASgNEg0KBXZhbHVlGAIgASgNOgI4",
+ "ARo2ChRNYXBVaW50NjRVaW50NjRFbnRyeRILCgNrZXkYASABKAQSDQoFdmFs",
+ "dWUYAiABKAQ6AjgBGjYKFE1hcFNpbnQzMlNpbnQzMkVudHJ5EgsKA2tleRgB",
+ "IAEoERINCgV2YWx1ZRgCIAEoEToCOAEaNgoUTWFwU2ludDY0U2ludDY0RW50",
+ "cnkSCwoDa2V5GAEgASgSEg0KBXZhbHVlGAIgASgSOgI4ARo4ChZNYXBGaXhl",
+ "ZDMyRml4ZWQzMkVudHJ5EgsKA2tleRgBIAEoBxINCgV2YWx1ZRgCIAEoBzoC",
+ "OAEaOAoWTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeRILCgNrZXkYASABKAYSDQoF",
+ "dmFsdWUYAiABKAY6AjgBGjoKGE1hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeRIL",
+ "CgNrZXkYASABKA8SDQoFdmFsdWUYAiABKA86AjgBGjoKGE1hcFNmaXhlZDY0",
+ "U2ZpeGVkNjRFbnRyeRILCgNrZXkYASABKBASDQoFdmFsdWUYAiABKBA6AjgB",
+ "GjQKEk1hcEludDMyRmxvYXRFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUY",
+ "AiABKAI6AjgBGjUKE01hcEludDMyRG91YmxlRW50cnkSCwoDa2V5GAEgASgF",
+ "Eg0KBXZhbHVlGAIgASgBOgI4ARoyChBNYXBCb29sQm9vbEVudHJ5EgsKA2tl",
+ "eRgBIAEoCBINCgV2YWx1ZRgCIAEoCDoCOAEaNgoUTWFwU3RyaW5nU3RyaW5n",
+ "RW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ARo0ChJNYXBJ",
+ "bnQzMkJ5dGVzRW50cnkSCwoDa2V5GAEgASgFEg0KBXZhbHVlGAIgASgMOgI4",
+ "ARpPChFNYXBJbnQzMkVudW1FbnRyeRILCgNrZXkYASABKAUSKQoFdmFsdWUY",
+ "AiABKA4yGi5wcm90b2J1Zl91bml0dGVzdC5NYXBFbnVtOgI4ARpgChtNYXBJ",
+ "bnQzMkZvcmVpZ25NZXNzYWdlRW50cnkSCwoDa2V5GAEgASgFEjAKBXZhbHVl",
+ "GAIgASgLMiEucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2U6AjgB",
+ "IkEKEVRlc3RNYXBTdWJtZXNzYWdlEiwKCHRlc3RfbWFwGAEgASgLMhoucHJv",
+ "dG9idWZfdW5pdHRlc3QuVGVzdE1hcCK8AQoOVGVzdE1lc3NhZ2VNYXASUQoR",
+ "bWFwX2ludDMyX21lc3NhZ2UYASADKAsyNi5wcm90b2J1Zl91bml0dGVzdC5U",
+ "ZXN0TWVzc2FnZU1hcC5NYXBJbnQzMk1lc3NhZ2VFbnRyeRpXChRNYXBJbnQz",
+ "Mk1lc3NhZ2VFbnRyeRILCgNrZXkYASABKAUSLgoFdmFsdWUYAiABKAsyHy5w",
+ "cm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXM6AjgBIuMBCg9UZXN0U2Ft",
+ "ZVR5cGVNYXASOgoEbWFwMRgBIAMoCzIsLnByb3RvYnVmX3VuaXR0ZXN0LlRl",
+ "c3RTYW1lVHlwZU1hcC5NYXAxRW50cnkSOgoEbWFwMhgCIAMoCzIsLnByb3Rv",
+ "YnVmX3VuaXR0ZXN0LlRlc3RTYW1lVHlwZU1hcC5NYXAyRW50cnkaKwoJTWFw",
+ "MUVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEaKwoJTWFw",
+ "MkVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEi5BAKDFRl",
+ "c3RBcmVuYU1hcBJLCg9tYXBfaW50MzJfaW50MzIYASADKAsyMi5wcm90b2J1",
+ "Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwSW50MzJJbnQzMkVudHJ5EksK",
+ "D21hcF9pbnQ2NF9pbnQ2NBgCIAMoCzIyLnByb3RvYnVmX3VuaXR0ZXN0LlRl",
+ "c3RBcmVuYU1hcC5NYXBJbnQ2NEludDY0RW50cnkSTwoRbWFwX3VpbnQzMl91",
+ "aW50MzIYAyADKAsyNC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAu",
+ "TWFwVWludDMyVWludDMyRW50cnkSTwoRbWFwX3VpbnQ2NF91aW50NjQYBCAD",
+ "KAsyNC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwVWludDY0",
+ "VWludDY0RW50cnkSTwoRbWFwX3NpbnQzMl9zaW50MzIYBSADKAsyNC5wcm90",
+ "b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwU2ludDMyU2ludDMyRW50",
+ "cnkSTwoRbWFwX3NpbnQ2NF9zaW50NjQYBiADKAsyNC5wcm90b2J1Zl91bml0",
+ "dGVzdC5UZXN0QXJlbmFNYXAuTWFwU2ludDY0U2ludDY0RW50cnkSUwoTbWFw",
+ "X2ZpeGVkMzJfZml4ZWQzMhgHIAMoCzI2LnByb3RvYnVmX3VuaXR0ZXN0LlRl",
+ "c3RBcmVuYU1hcC5NYXBGaXhlZDMyRml4ZWQzMkVudHJ5ElMKE21hcF9maXhl",
+ "ZDY0X2ZpeGVkNjQYCCADKAsyNi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJl",
+ "bmFNYXAuTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeRJXChVtYXBfc2ZpeGVkMzJf",
+ "c2ZpeGVkMzIYCSADKAsyOC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFN",
+ "YXAuTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5ElcKFW1hcF9zZml4ZWQ2NF9z",
+ "Zml4ZWQ2NBgKIAMoCzI4LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBcmVuYU1h",
+ "cC5NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkSSwoPbWFwX2ludDMyX2Zsb2F0",
+ "GAsgAygLMjIucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwLk1hcElu",
+ "dDMyRmxvYXRFbnRyeRJNChBtYXBfaW50MzJfZG91YmxlGAwgAygLMjMucHJv",
+ "dG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwLk1hcEludDMyRG91YmxlRW50",
+ "cnkSRwoNbWFwX2Jvb2xfYm9vbBgNIAMoCzIwLnByb3RvYnVmX3VuaXR0ZXN0",
+ "LlRlc3RBcmVuYU1hcC5NYXBCb29sQm9vbEVudHJ5EkkKDm1hcF9pbnQzMl9l",
+ "bnVtGA4gAygLMjEucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwLk1h",
+ "cEludDMyRW51bUVudHJ5El4KGW1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UY",
+ "DyADKAsyOy5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwSW50",
+ "MzJGb3JlaWduTWVzc2FnZUVudHJ5GjQKEk1hcEludDMySW50MzJFbnRyeRIL",
+ "CgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAU6AjgBGjQKEk1hcEludDY0SW50",
+ "NjRFbnRyeRILCgNrZXkYASABKAMSDQoFdmFsdWUYAiABKAM6AjgBGjYKFE1h",
+ "cFVpbnQzMlVpbnQzMkVudHJ5EgsKA2tleRgBIAEoDRINCgV2YWx1ZRgCIAEo",
+ "DToCOAEaNgoUTWFwVWludDY0VWludDY0RW50cnkSCwoDa2V5GAEgASgEEg0K",
+ "BXZhbHVlGAIgASgEOgI4ARo2ChRNYXBTaW50MzJTaW50MzJFbnRyeRILCgNr",
+ "ZXkYASABKBESDQoFdmFsdWUYAiABKBE6AjgBGjYKFE1hcFNpbnQ2NFNpbnQ2",
+ "NEVudHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1ZRgCIAEoEjoCOAEaOAoWTWFw",
+ "Rml4ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkYASABKAcSDQoFdmFsdWUYAiAB",
+ "KAc6AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSCwoDa2V5GAEgASgG",
+ "Eg0KBXZhbHVlGAIgASgGOgI4ARo6ChhNYXBTZml4ZWQzMlNmaXhlZDMyRW50",
+ "cnkSCwoDa2V5GAEgASgPEg0KBXZhbHVlGAIgASgPOgI4ARo6ChhNYXBTZml4",
+ "ZWQ2NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEgASgQEg0KBXZhbHVlGAIgASgQ",
+ "OgI4ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkSCwoDa2V5GAEgASgFEg0KBXZh",
+ "bHVlGAIgASgCOgI4ARo1ChNNYXBJbnQzMkRvdWJsZUVudHJ5EgsKA2tleRgB",
+ "IAEoBRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQTWFwQm9vbEJvb2xFbnRyeRIL",
+ "CgNrZXkYASABKAgSDQoFdmFsdWUYAiABKAg6AjgBGk8KEU1hcEludDMyRW51",
+ "bUVudHJ5EgsKA2tleRgBIAEoBRIpCgV2YWx1ZRgCIAEoDjIaLnByb3RvYnVm",
+ "X3VuaXR0ZXN0Lk1hcEVudW06AjgBGmAKG01hcEludDMyRm9yZWlnbk1lc3Nh",
+ "Z2VFbnRyeRILCgNrZXkYASABKAUSMAoFdmFsdWUYAiABKAsyIS5wcm90b2J1",
+ "Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZToCOAEi5AEKH01lc3NhZ2VDb250",
+ "YWluaW5nRW51bUNhbGxlZFR5cGUSSgoEdHlwZRgBIAMoCzI8LnByb3RvYnVm",
+ "X3VuaXR0ZXN0Lk1lc3NhZ2VDb250YWluaW5nRW51bUNhbGxlZFR5cGUuVHlw",
+ "ZUVudHJ5Gl8KCVR5cGVFbnRyeRILCgNrZXkYASABKAUSQQoFdmFsdWUYAiAB",
+ "KAsyMi5wcm90b2J1Zl91bml0dGVzdC5NZXNzYWdlQ29udGFpbmluZ0VudW1D",
+ "YWxsZWRUeXBlOgI4ASIUCgRUeXBlEgwKCFRZUEVfRk9PEAAinQEKH01lc3Nh",
+ "Z2VDb250YWluaW5nTWFwQ2FsbGVkRW50cnkSTAoFZW50cnkYASADKAsyPS5w",
+ "cm90b2J1Zl91bml0dGVzdC5NZXNzYWdlQ29udGFpbmluZ01hcENhbGxlZEVu",
+ "dHJ5LkVudHJ5RW50cnkaLAoKRW50cnlFbnRyeRILCgNrZXkYASABKAUSDQoF",
+ "dmFsdWUYAiABKAU6AjgBKj8KB01hcEVudW0SEAoMTUFQX0VOVU1fRk9PEAAS",
+ "EAoMTUFQX0VOVU1fQkFSEAESEAoMTUFQX0VOVU1fQkFaEAJCIPgBAaoCGkdv",
"b2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zYgZwcm90bzM="));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor, },
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs
index bf527ac5..b2a97ce5 100644
--- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs
+++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs
@@ -21,13 +21,13 @@ namespace Google.Protobuf.TestProtos {
static UnittestImportProto3() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "Cixnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3Byb3RvMy5wcm90",
- "bxIYcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0GjNnb29nbGUvcHJvdG9idWYv",
- "dW5pdHRlc3RfaW1wb3J0X3B1YmxpY19wcm90bzMucHJvdG8iGgoNSW1wb3J0",
- "TWVzc2FnZRIJCgFkGAEgASgFKlkKCkltcG9ydEVudW0SGwoXSU1QT1JUX0VO",
- "VU1fVU5TUEVDSUZJRUQQABIOCgpJTVBPUlRfRk9PEAcSDgoKSU1QT1JUX0JB",
- "UhAIEg4KCklNUE9SVF9CQVoQCUI8Chhjb20uZ29vZ2xlLnByb3RvYnVmLnRl",
- "c3RIAfgBAaoCGkdvb2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zUABiBnByb3Rv",
+ "Cixnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3Byb3RvMy5wcm90",
+ "bxIYcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0GjNnb29nbGUvcHJvdG9idWYv",
+ "dW5pdHRlc3RfaW1wb3J0X3B1YmxpY19wcm90bzMucHJvdG8iGgoNSW1wb3J0",
+ "TWVzc2FnZRIJCgFkGAEgASgFKlkKCkltcG9ydEVudW0SGwoXSU1QT1JUX0VO",
+ "VU1fVU5TUEVDSUZJRUQQABIOCgpJTVBPUlRfRk9PEAcSDgoKSU1QT1JUX0JB",
+ "UhAIEg4KCklNUE9SVF9CQVoQCUI8Chhjb20uZ29vZ2xlLnByb3RvYnVmLnRl",
+ "c3RIAfgBAaoCGkdvb2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zUABiBnByb3Rv",
"Mw=="));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportPublicProto3.Descriptor, },
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs
index ec460906..ca3cab26 100644
--- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs
+++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs
@@ -21,9 +21,9 @@ namespace Google.Protobuf.TestProtos {
static UnittestImportPublicProto3() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "CjNnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3B1YmxpY19wcm90",
- "bzMucHJvdG8SGHByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydCIgChNQdWJsaWNJ",
- "bXBvcnRNZXNzYWdlEgkKAWUYASABKAVCNwoYY29tLmdvb2dsZS5wcm90b2J1",
+ "CjNnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3B1YmxpY19wcm90",
+ "bzMucHJvdG8SGHByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydCIgChNQdWJsaWNJ",
+ "bXBvcnRNZXNzYWdlEgkKAWUYASABKAVCNwoYY29tLmdvb2dsZS5wcm90b2J1",
"Zi50ZXN0qgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw=="));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { },
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs
index 63119a34..80eb67b0 100644
--- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs
+++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs
@@ -21,28 +21,28 @@ namespace UnitTest.Issues.TestProtos {
static UnittestIssues() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "ChV1bml0dGVzdF9pc3N1ZXMucHJvdG8SD3VuaXR0ZXN0X2lzc3VlcyInCghJ",
- "c3N1ZTMwNxobCgpOZXN0ZWRPbmNlGg0KC05lc3RlZFR3aWNlIrABChNOZWdh",
- "dGl2ZUVudW1NZXNzYWdlEiwKBXZhbHVlGAEgASgOMh0udW5pdHRlc3RfaXNz",
- "dWVzLk5lZ2F0aXZlRW51bRIxCgZ2YWx1ZXMYAiADKA4yHS51bml0dGVzdF9p",
- "c3N1ZXMuTmVnYXRpdmVFbnVtQgIQABI4Cg1wYWNrZWRfdmFsdWVzGAMgAygO",
- "Mh0udW5pdHRlc3RfaXNzdWVzLk5lZ2F0aXZlRW51bUICEAEiEQoPRGVwcmVj",
- "YXRlZENoaWxkIrkCChdEZXByZWNhdGVkRmllbGRzTWVzc2FnZRIaCg5Qcmlt",
- "aXRpdmVWYWx1ZRgBIAEoBUICGAESGgoOUHJpbWl0aXZlQXJyYXkYAiADKAVC",
- "AhgBEjoKDE1lc3NhZ2VWYWx1ZRgDIAEoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5E",
- "ZXByZWNhdGVkQ2hpbGRCAhgBEjoKDE1lc3NhZ2VBcnJheRgEIAMoCzIgLnVu",
- "aXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkQ2hpbGRCAhgBEjYKCUVudW1WYWx1",
- "ZRgFIAEoDjIfLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkRW51bUICGAES",
- "NgoJRW51bUFycmF5GAYgAygOMh8udW5pdHRlc3RfaXNzdWVzLkRlcHJlY2F0",
- "ZWRFbnVtQgIYASIZCglJdGVtRmllbGQSDAoEaXRlbRgBIAEoBSJECg1SZXNl",
- "cnZlZE5hbWVzEg0KBXR5cGVzGAEgASgFEhIKCmRlc2NyaXB0b3IYAiABKAUa",
- "EAoOU29tZU5lc3RlZFR5cGUioAEKFVRlc3RKc29uRmllbGRPcmRlcmluZxIT",
- "CgtwbGFpbl9pbnQzMhgEIAEoBRITCglvMV9zdHJpbmcYAiABKAlIABISCghv",
- "MV9pbnQzMhgFIAEoBUgAEhQKDHBsYWluX3N0cmluZxgBIAEoCRISCghvMl9p",
- "bnQzMhgGIAEoBUgBEhMKCW8yX3N0cmluZxgDIAEoCUgBQgQKAm8xQgQKAm8y",
- "KlUKDE5lZ2F0aXZlRW51bRIWChJORUdBVElWRV9FTlVNX1pFUk8QABIWCglG",
- "aXZlQmVsb3cQ+///////////ARIVCghNaW51c09uZRD///////////8BKi4K",
- "DkRlcHJlY2F0ZWRFbnVtEhMKD0RFUFJFQ0FURURfWkVSTxAAEgcKA29uZRAB",
+ "ChV1bml0dGVzdF9pc3N1ZXMucHJvdG8SD3VuaXR0ZXN0X2lzc3VlcyInCghJ",
+ "c3N1ZTMwNxobCgpOZXN0ZWRPbmNlGg0KC05lc3RlZFR3aWNlIrABChNOZWdh",
+ "dGl2ZUVudW1NZXNzYWdlEiwKBXZhbHVlGAEgASgOMh0udW5pdHRlc3RfaXNz",
+ "dWVzLk5lZ2F0aXZlRW51bRIxCgZ2YWx1ZXMYAiADKA4yHS51bml0dGVzdF9p",
+ "c3N1ZXMuTmVnYXRpdmVFbnVtQgIQABI4Cg1wYWNrZWRfdmFsdWVzGAMgAygO",
+ "Mh0udW5pdHRlc3RfaXNzdWVzLk5lZ2F0aXZlRW51bUICEAEiEQoPRGVwcmVj",
+ "YXRlZENoaWxkIrkCChdEZXByZWNhdGVkRmllbGRzTWVzc2FnZRIaCg5Qcmlt",
+ "aXRpdmVWYWx1ZRgBIAEoBUICGAESGgoOUHJpbWl0aXZlQXJyYXkYAiADKAVC",
+ "AhgBEjoKDE1lc3NhZ2VWYWx1ZRgDIAEoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5E",
+ "ZXByZWNhdGVkQ2hpbGRCAhgBEjoKDE1lc3NhZ2VBcnJheRgEIAMoCzIgLnVu",
+ "aXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkQ2hpbGRCAhgBEjYKCUVudW1WYWx1",
+ "ZRgFIAEoDjIfLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkRW51bUICGAES",
+ "NgoJRW51bUFycmF5GAYgAygOMh8udW5pdHRlc3RfaXNzdWVzLkRlcHJlY2F0",
+ "ZWRFbnVtQgIYASIZCglJdGVtRmllbGQSDAoEaXRlbRgBIAEoBSJECg1SZXNl",
+ "cnZlZE5hbWVzEg0KBXR5cGVzGAEgASgFEhIKCmRlc2NyaXB0b3IYAiABKAUa",
+ "EAoOU29tZU5lc3RlZFR5cGUioAEKFVRlc3RKc29uRmllbGRPcmRlcmluZxIT",
+ "CgtwbGFpbl9pbnQzMhgEIAEoBRITCglvMV9zdHJpbmcYAiABKAlIABISCghv",
+ "MV9pbnQzMhgFIAEoBUgAEhQKDHBsYWluX3N0cmluZxgBIAEoCRISCghvMl9p",
+ "bnQzMhgGIAEoBUgBEhMKCW8yX3N0cmluZxgDIAEoCUgBQgQKAm8xQgQKAm8y",
+ "KlUKDE5lZ2F0aXZlRW51bRIWChJORUdBVElWRV9FTlVNX1pFUk8QABIWCglG",
+ "aXZlQmVsb3cQ+///////////ARIVCghNaW51c09uZRD///////////8BKi4K",
+ "DkRlcHJlY2F0ZWRFbnVtEhMKD0RFUFJFQ0FURURfWkVSTxAAEgcKA29uZRAB",
"Qh9IAaoCGlVuaXRUZXN0Lklzc3Vlcy5UZXN0UHJvdG9zYgZwcm90bzM="));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { },
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs
index bf4590ad..49c357ea 100644
--- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs
+++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs
@@ -21,132 +21,132 @@ namespace Google.Protobuf.TestProtos {
static UnittestProto3() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "CiVnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfcHJvdG8zLnByb3RvEhFwcm90",
- "b2J1Zl91bml0dGVzdBosZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2ltcG9y",
- "dF9wcm90bzMucHJvdG8i8A8KDFRlc3RBbGxUeXBlcxIUCgxzaW5nbGVfaW50",
- "MzIYASABKAUSFAoMc2luZ2xlX2ludDY0GAIgASgDEhUKDXNpbmdsZV91aW50",
- "MzIYAyABKA0SFQoNc2luZ2xlX3VpbnQ2NBgEIAEoBBIVCg1zaW5nbGVfc2lu",
- "dDMyGAUgASgREhUKDXNpbmdsZV9zaW50NjQYBiABKBISFgoOc2luZ2xlX2Zp",
- "eGVkMzIYByABKAcSFgoOc2luZ2xlX2ZpeGVkNjQYCCABKAYSFwoPc2luZ2xl",
- "X3NmaXhlZDMyGAkgASgPEhcKD3NpbmdsZV9zZml4ZWQ2NBgKIAEoEBIUCgxz",
- "aW5nbGVfZmxvYXQYCyABKAISFQoNc2luZ2xlX2RvdWJsZRgMIAEoARITCgtz",
- "aW5nbGVfYm9vbBgNIAEoCBIVCg1zaW5nbGVfc3RyaW5nGA4gASgJEhQKDHNp",
- "bmdsZV9ieXRlcxgPIAEoDBJMChVzaW5nbGVfbmVzdGVkX21lc3NhZ2UYEiAB",
- "KAsyLS5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMuTmVzdGVkTWVz",
- "c2FnZRJBChZzaW5nbGVfZm9yZWlnbl9tZXNzYWdlGBMgASgLMiEucHJvdG9i",
- "dWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2USRgoVc2luZ2xlX2ltcG9ydF9t",
- "ZXNzYWdlGBQgASgLMicucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9y",
- "dE1lc3NhZ2USRgoSc2luZ2xlX25lc3RlZF9lbnVtGBUgASgOMioucHJvdG9i",
- "dWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzLk5lc3RlZEVudW0SOwoTc2luZ2xl",
- "X2ZvcmVpZ25fZW51bRgWIAEoDjIeLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVp",
- "Z25FbnVtEkAKEnNpbmdsZV9pbXBvcnRfZW51bRgXIAEoDjIkLnByb3RvYnVm",
- "X3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtElMKHHNpbmdsZV9wdWJsaWNf",
- "aW1wb3J0X21lc3NhZ2UYGiABKAsyLS5wcm90b2J1Zl91bml0dGVzdF9pbXBv",
- "cnQuUHVibGljSW1wb3J0TWVzc2FnZRIWCg5yZXBlYXRlZF9pbnQzMhgfIAMo",
- "BRIWCg5yZXBlYXRlZF9pbnQ2NBggIAMoAxIXCg9yZXBlYXRlZF91aW50MzIY",
- "ISADKA0SFwoPcmVwZWF0ZWRfdWludDY0GCIgAygEEhcKD3JlcGVhdGVkX3Np",
- "bnQzMhgjIAMoERIXCg9yZXBlYXRlZF9zaW50NjQYJCADKBISGAoQcmVwZWF0",
- "ZWRfZml4ZWQzMhglIAMoBxIYChByZXBlYXRlZF9maXhlZDY0GCYgAygGEhkK",
- "EXJlcGVhdGVkX3NmaXhlZDMyGCcgAygPEhkKEXJlcGVhdGVkX3NmaXhlZDY0",
- "GCggAygQEhYKDnJlcGVhdGVkX2Zsb2F0GCkgAygCEhcKD3JlcGVhdGVkX2Rv",
- "dWJsZRgqIAMoARIVCg1yZXBlYXRlZF9ib29sGCsgAygIEhcKD3JlcGVhdGVk",
- "X3N0cmluZxgsIAMoCRIWCg5yZXBlYXRlZF9ieXRlcxgtIAMoDBJOChdyZXBl",
- "YXRlZF9uZXN0ZWRfbWVzc2FnZRgwIAMoCzItLnByb3RvYnVmX3VuaXR0ZXN0",
- "LlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlEkMKGHJlcGVhdGVkX2ZvcmVp",
- "Z25fbWVzc2FnZRgxIAMoCzIhLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25N",
- "ZXNzYWdlEkgKF3JlcGVhdGVkX2ltcG9ydF9tZXNzYWdlGDIgAygLMicucHJv",
- "dG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2USSAoUcmVwZWF0",
- "ZWRfbmVzdGVkX2VudW0YMyADKA4yKi5wcm90b2J1Zl91bml0dGVzdC5UZXN0",
- "QWxsVHlwZXMuTmVzdGVkRW51bRI9ChVyZXBlYXRlZF9mb3JlaWduX2VudW0Y",
- "NCADKA4yHi5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bRJCChRyZXBl",
- "YXRlZF9pbXBvcnRfZW51bRg1IAMoDjIkLnByb3RvYnVmX3VuaXR0ZXN0X2lt",
- "cG9ydC5JbXBvcnRFbnVtElUKHnJlcGVhdGVkX3B1YmxpY19pbXBvcnRfbWVz",
- "c2FnZRg2IAMoCzItLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJ",
- "bXBvcnRNZXNzYWdlEhYKDG9uZW9mX3VpbnQzMhhvIAEoDUgAEk0KFG9uZW9m",
- "X25lc3RlZF9tZXNzYWdlGHAgASgLMi0ucHJvdG9idWZfdW5pdHRlc3QuVGVz",
- "dEFsbFR5cGVzLk5lc3RlZE1lc3NhZ2VIABIWCgxvbmVvZl9zdHJpbmcYcSAB",
- "KAlIABIVCgtvbmVvZl9ieXRlcxhyIAEoDEgAGhsKDU5lc3RlZE1lc3NhZ2US",
- "CgoCYmIYASABKAUiVgoKTmVzdGVkRW51bRIbChdORVNURURfRU5VTV9VTlNQ",
- "RUNJRklFRBAAEgcKA0ZPTxABEgcKA0JBUhACEgcKA0JBWhADEhAKA05FRxD/",
- "//////////8BQg0KC29uZW9mX2ZpZWxkIrsBChJOZXN0ZWRUZXN0QWxsVHlw",
- "ZXMSNAoFY2hpbGQYASABKAsyJS5wcm90b2J1Zl91bml0dGVzdC5OZXN0ZWRU",
- "ZXN0QWxsVHlwZXMSMAoHcGF5bG9hZBgCIAEoCzIfLnByb3RvYnVmX3VuaXR0",
- "ZXN0LlRlc3RBbGxUeXBlcxI9Cg5yZXBlYXRlZF9jaGlsZBgDIAMoCzIlLnBy",
- "b3RvYnVmX3VuaXR0ZXN0Lk5lc3RlZFRlc3RBbGxUeXBlcyI0ChRUZXN0RGVw",
- "cmVjYXRlZEZpZWxkcxIcChBkZXByZWNhdGVkX2ludDMyGAEgASgFQgIYASIb",
- "Cg5Gb3JlaWduTWVzc2FnZRIJCgFjGAEgASgFIjAKElRlc3RSZXNlcnZlZEZp",
- "ZWxkc0oECAIQA0oECA8QEEoECAkQDFIDYmFyUgNiYXoiWgoRVGVzdEZvcmVp",
- "Z25OZXN0ZWQSRQoOZm9yZWlnbl9uZXN0ZWQYASABKAsyLS5wcm90b2J1Zl91",
- "bml0dGVzdC5UZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZSI0ChhUZXN0UmVh",
- "bGx5TGFyZ2VUYWdOdW1iZXISCQoBYRgBIAEoBRINCgJiYhj///9/IAEoBSJV",
- "ChRUZXN0UmVjdXJzaXZlTWVzc2FnZRIyCgFhGAEgASgLMicucHJvdG9idWZf",
- "dW5pdHRlc3QuVGVzdFJlY3Vyc2l2ZU1lc3NhZ2USCQoBaRgCIAEoBSJLChRU",
- "ZXN0TXV0dWFsUmVjdXJzaW9uQRIzCgJiYhgBIAEoCzInLnByb3RvYnVmX3Vu",
- "aXR0ZXN0LlRlc3RNdXR1YWxSZWN1cnNpb25CImIKFFRlc3RNdXR1YWxSZWN1",
- "cnNpb25CEjIKAWEYASABKAsyJy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TXV0",
- "dWFsUmVjdXJzaW9uQRIWCg5vcHRpb25hbF9pbnQzMhgCIAEoBSLrAgoXVGVz",
- "dENhbWVsQ2FzZUZpZWxkTmFtZXMSFgoOUHJpbWl0aXZlRmllbGQYASABKAUS",
- "EwoLU3RyaW5nRmllbGQYAiABKAkSMQoJRW51bUZpZWxkGAMgASgOMh4ucHJv",
- "dG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW0SNwoMTWVzc2FnZUZpZWxkGAQg",
- "ASgLMiEucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2USHgoWUmVw",
- "ZWF0ZWRQcmltaXRpdmVGaWVsZBgHIAMoBRIbChNSZXBlYXRlZFN0cmluZ0Zp",
- "ZWxkGAggAygJEjkKEVJlcGVhdGVkRW51bUZpZWxkGAkgAygOMh4ucHJvdG9i",
- "dWZfdW5pdHRlc3QuRm9yZWlnbkVudW0SPwoUUmVwZWF0ZWRNZXNzYWdlRmll",
- "bGQYCiADKAsyIS5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZSLH",
- "AQoSVGVzdEZpZWxkT3JkZXJpbmdzEhEKCW15X3N0cmluZxgLIAEoCRIOCgZt",
- "eV9pbnQYASABKAMSEAoIbXlfZmxvYXQYZSABKAISUwoVc2luZ2xlX25lc3Rl",
- "ZF9tZXNzYWdlGMgBIAEoCzIzLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RGaWVs",
- "ZE9yZGVyaW5ncy5OZXN0ZWRNZXNzYWdlGicKDU5lc3RlZE1lc3NhZ2USCgoC",
- "b28YAiABKAMSCgoCYmIYASABKAUiSwoRU3BhcnNlRW51bU1lc3NhZ2USNgoL",
- "c3BhcnNlX2VudW0YASABKA4yIS5wcm90b2J1Zl91bml0dGVzdC5UZXN0U3Bh",
- "cnNlRW51bSIZCglPbmVTdHJpbmcSDAoEZGF0YRgBIAEoCSIaCgpNb3JlU3Ry",
- "aW5nEgwKBGRhdGEYASADKAkiGAoIT25lQnl0ZXMSDAoEZGF0YRgBIAEoDCIZ",
- "CglNb3JlQnl0ZXMSDAoEZGF0YRgBIAEoDCIcCgxJbnQzMk1lc3NhZ2USDAoE",
- "ZGF0YRgBIAEoBSIdCg1VaW50MzJNZXNzYWdlEgwKBGRhdGEYASABKA0iHAoM",
- "SW50NjRNZXNzYWdlEgwKBGRhdGEYASABKAMiHQoNVWludDY0TWVzc2FnZRIM",
- "CgRkYXRhGAEgASgEIhsKC0Jvb2xNZXNzYWdlEgwKBGRhdGEYASABKAgicwoJ",
- "VGVzdE9uZW9mEhEKB2Zvb19pbnQYASABKAVIABIUCgpmb29fc3RyaW5nGAIg",
- "ASgJSAASNgoLZm9vX21lc3NhZ2UYAyABKAsyHy5wcm90b2J1Zl91bml0dGVz",
- "dC5UZXN0QWxsVHlwZXNIAEIFCgNmb28iqgMKD1Rlc3RQYWNrZWRUeXBlcxIY",
- "CgxwYWNrZWRfaW50MzIYWiADKAVCAhABEhgKDHBhY2tlZF9pbnQ2NBhbIAMo",
- "A0ICEAESGQoNcGFja2VkX3VpbnQzMhhcIAMoDUICEAESGQoNcGFja2VkX3Vp",
- "bnQ2NBhdIAMoBEICEAESGQoNcGFja2VkX3NpbnQzMhheIAMoEUICEAESGQoN",
- "cGFja2VkX3NpbnQ2NBhfIAMoEkICEAESGgoOcGFja2VkX2ZpeGVkMzIYYCAD",
- "KAdCAhABEhoKDnBhY2tlZF9maXhlZDY0GGEgAygGQgIQARIbCg9wYWNrZWRf",
- "c2ZpeGVkMzIYYiADKA9CAhABEhsKD3BhY2tlZF9zZml4ZWQ2NBhjIAMoEEIC",
- "EAESGAoMcGFja2VkX2Zsb2F0GGQgAygCQgIQARIZCg1wYWNrZWRfZG91Ymxl",
- "GGUgAygBQgIQARIXCgtwYWNrZWRfYm9vbBhmIAMoCEICEAESNwoLcGFja2Vk",
- "X2VudW0YZyADKA4yHi5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUIC",
- "EAEiyAMKEVRlc3RVbnBhY2tlZFR5cGVzEhoKDnVucGFja2VkX2ludDMyGFog",
- "AygFQgIQABIaCg51bnBhY2tlZF9pbnQ2NBhbIAMoA0ICEAASGwoPdW5wYWNr",
- "ZWRfdWludDMyGFwgAygNQgIQABIbCg91bnBhY2tlZF91aW50NjQYXSADKARC",
- "AhAAEhsKD3VucGFja2VkX3NpbnQzMhheIAMoEUICEAASGwoPdW5wYWNrZWRf",
- "c2ludDY0GF8gAygSQgIQABIcChB1bnBhY2tlZF9maXhlZDMyGGAgAygHQgIQ",
- "ABIcChB1bnBhY2tlZF9maXhlZDY0GGEgAygGQgIQABIdChF1bnBhY2tlZF9z",
- "Zml4ZWQzMhhiIAMoD0ICEAASHQoRdW5wYWNrZWRfc2ZpeGVkNjQYYyADKBBC",
- "AhAAEhoKDnVucGFja2VkX2Zsb2F0GGQgAygCQgIQABIbCg91bnBhY2tlZF9k",
- "b3VibGUYZSADKAFCAhAAEhkKDXVucGFja2VkX2Jvb2wYZiADKAhCAhAAEjkK",
- "DXVucGFja2VkX2VudW0YZyADKA4yHi5wcm90b2J1Zl91bml0dGVzdC5Gb3Jl",
- "aWduRW51bUICEAAiwAEKI1Rlc3RSZXBlYXRlZFNjYWxhckRpZmZlcmVudFRh",
- "Z1NpemVzEhgKEHJlcGVhdGVkX2ZpeGVkMzIYDCADKAcSFgoOcmVwZWF0ZWRf",
- "aW50MzIYDSADKAUSGQoQcmVwZWF0ZWRfZml4ZWQ2NBj+DyADKAYSFwoOcmVw",
- "ZWF0ZWRfaW50NjQY/w8gAygDEhgKDnJlcGVhdGVkX2Zsb2F0GP7/DyADKAIS",
- "GQoPcmVwZWF0ZWRfdWludDY0GP//DyADKAQiKAobVGVzdENvbW1lbnRJbmpl",
- "Y3Rpb25NZXNzYWdlEgkKAWEYASABKAkiDAoKRm9vUmVxdWVzdCINCgtGb29S",
- "ZXNwb25zZSISChBGb29DbGllbnRNZXNzYWdlIhIKEEZvb1NlcnZlck1lc3Nh",
- "Z2UiDAoKQmFyUmVxdWVzdCINCgtCYXJSZXNwb25zZSpZCgtGb3JlaWduRW51",
- "bRIXChNGT1JFSUdOX1VOU1BFQ0lGSUVEEAASDwoLRk9SRUlHTl9GT08QBBIP",
- "CgtGT1JFSUdOX0JBUhAFEg8KC0ZPUkVJR05fQkFaEAYqdQoUVGVzdEVudW1X",
- "aXRoRHVwVmFsdWUSKAokVEVTVF9FTlVNX1dJVEhfRFVQX1ZBTFVFX1VOU1BF",
- "Q0lGSUVEEAASCAoERk9PMRABEggKBEJBUjEQAhIHCgNCQVoQAxIICgRGT08y",
- "EAESCAoEQkFSMhACGgIQASqdAQoOVGVzdFNwYXJzZUVudW0SIAocVEVTVF9T",
- "UEFSU0VfRU5VTV9VTlNQRUNJRklFRBAAEgwKCFNQQVJTRV9BEHsSDgoIU1BB",
- "UlNFX0IQpucDEg8KCFNQQVJTRV9DELKxgAYSFQoIU1BBUlNFX0QQ8f//////",
- "////ARIVCghTUEFSU0VfRRC03vz///////8BEgwKCFNQQVJTRV9HEAIymQEK",
- "C1Rlc3RTZXJ2aWNlEkQKA0ZvbxIdLnByb3RvYnVmX3VuaXR0ZXN0LkZvb1Jl",
- "cXVlc3QaHi5wcm90b2J1Zl91bml0dGVzdC5Gb29SZXNwb25zZRJECgNCYXIS",
- "HS5wcm90b2J1Zl91bml0dGVzdC5CYXJSZXF1ZXN0Gh4ucHJvdG9idWZfdW5p",
- "dHRlc3QuQmFyUmVzcG9uc2VCOkINVW5pdHRlc3RQcm90b0gBgAEBiAEBkAEB",
+ "CiVnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfcHJvdG8zLnByb3RvEhFwcm90",
+ "b2J1Zl91bml0dGVzdBosZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2ltcG9y",
+ "dF9wcm90bzMucHJvdG8i8A8KDFRlc3RBbGxUeXBlcxIUCgxzaW5nbGVfaW50",
+ "MzIYASABKAUSFAoMc2luZ2xlX2ludDY0GAIgASgDEhUKDXNpbmdsZV91aW50",
+ "MzIYAyABKA0SFQoNc2luZ2xlX3VpbnQ2NBgEIAEoBBIVCg1zaW5nbGVfc2lu",
+ "dDMyGAUgASgREhUKDXNpbmdsZV9zaW50NjQYBiABKBISFgoOc2luZ2xlX2Zp",
+ "eGVkMzIYByABKAcSFgoOc2luZ2xlX2ZpeGVkNjQYCCABKAYSFwoPc2luZ2xl",
+ "X3NmaXhlZDMyGAkgASgPEhcKD3NpbmdsZV9zZml4ZWQ2NBgKIAEoEBIUCgxz",
+ "aW5nbGVfZmxvYXQYCyABKAISFQoNc2luZ2xlX2RvdWJsZRgMIAEoARITCgtz",
+ "aW5nbGVfYm9vbBgNIAEoCBIVCg1zaW5nbGVfc3RyaW5nGA4gASgJEhQKDHNp",
+ "bmdsZV9ieXRlcxgPIAEoDBJMChVzaW5nbGVfbmVzdGVkX21lc3NhZ2UYEiAB",
+ "KAsyLS5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMuTmVzdGVkTWVz",
+ "c2FnZRJBChZzaW5nbGVfZm9yZWlnbl9tZXNzYWdlGBMgASgLMiEucHJvdG9i",
+ "dWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2USRgoVc2luZ2xlX2ltcG9ydF9t",
+ "ZXNzYWdlGBQgASgLMicucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9y",
+ "dE1lc3NhZ2USRgoSc2luZ2xlX25lc3RlZF9lbnVtGBUgASgOMioucHJvdG9i",
+ "dWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzLk5lc3RlZEVudW0SOwoTc2luZ2xl",
+ "X2ZvcmVpZ25fZW51bRgWIAEoDjIeLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVp",
+ "Z25FbnVtEkAKEnNpbmdsZV9pbXBvcnRfZW51bRgXIAEoDjIkLnByb3RvYnVm",
+ "X3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtElMKHHNpbmdsZV9wdWJsaWNf",
+ "aW1wb3J0X21lc3NhZ2UYGiABKAsyLS5wcm90b2J1Zl91bml0dGVzdF9pbXBv",
+ "cnQuUHVibGljSW1wb3J0TWVzc2FnZRIWCg5yZXBlYXRlZF9pbnQzMhgfIAMo",
+ "BRIWCg5yZXBlYXRlZF9pbnQ2NBggIAMoAxIXCg9yZXBlYXRlZF91aW50MzIY",
+ "ISADKA0SFwoPcmVwZWF0ZWRfdWludDY0GCIgAygEEhcKD3JlcGVhdGVkX3Np",
+ "bnQzMhgjIAMoERIXCg9yZXBlYXRlZF9zaW50NjQYJCADKBISGAoQcmVwZWF0",
+ "ZWRfZml4ZWQzMhglIAMoBxIYChByZXBlYXRlZF9maXhlZDY0GCYgAygGEhkK",
+ "EXJlcGVhdGVkX3NmaXhlZDMyGCcgAygPEhkKEXJlcGVhdGVkX3NmaXhlZDY0",
+ "GCggAygQEhYKDnJlcGVhdGVkX2Zsb2F0GCkgAygCEhcKD3JlcGVhdGVkX2Rv",
+ "dWJsZRgqIAMoARIVCg1yZXBlYXRlZF9ib29sGCsgAygIEhcKD3JlcGVhdGVk",
+ "X3N0cmluZxgsIAMoCRIWCg5yZXBlYXRlZF9ieXRlcxgtIAMoDBJOChdyZXBl",
+ "YXRlZF9uZXN0ZWRfbWVzc2FnZRgwIAMoCzItLnByb3RvYnVmX3VuaXR0ZXN0",
+ "LlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlEkMKGHJlcGVhdGVkX2ZvcmVp",
+ "Z25fbWVzc2FnZRgxIAMoCzIhLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25N",
+ "ZXNzYWdlEkgKF3JlcGVhdGVkX2ltcG9ydF9tZXNzYWdlGDIgAygLMicucHJv",
+ "dG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2USSAoUcmVwZWF0",
+ "ZWRfbmVzdGVkX2VudW0YMyADKA4yKi5wcm90b2J1Zl91bml0dGVzdC5UZXN0",
+ "QWxsVHlwZXMuTmVzdGVkRW51bRI9ChVyZXBlYXRlZF9mb3JlaWduX2VudW0Y",
+ "NCADKA4yHi5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bRJCChRyZXBl",
+ "YXRlZF9pbXBvcnRfZW51bRg1IAMoDjIkLnByb3RvYnVmX3VuaXR0ZXN0X2lt",
+ "cG9ydC5JbXBvcnRFbnVtElUKHnJlcGVhdGVkX3B1YmxpY19pbXBvcnRfbWVz",
+ "c2FnZRg2IAMoCzItLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJ",
+ "bXBvcnRNZXNzYWdlEhYKDG9uZW9mX3VpbnQzMhhvIAEoDUgAEk0KFG9uZW9m",
+ "X25lc3RlZF9tZXNzYWdlGHAgASgLMi0ucHJvdG9idWZfdW5pdHRlc3QuVGVz",
+ "dEFsbFR5cGVzLk5lc3RlZE1lc3NhZ2VIABIWCgxvbmVvZl9zdHJpbmcYcSAB",
+ "KAlIABIVCgtvbmVvZl9ieXRlcxhyIAEoDEgAGhsKDU5lc3RlZE1lc3NhZ2US",
+ "CgoCYmIYASABKAUiVgoKTmVzdGVkRW51bRIbChdORVNURURfRU5VTV9VTlNQ",
+ "RUNJRklFRBAAEgcKA0ZPTxABEgcKA0JBUhACEgcKA0JBWhADEhAKA05FRxD/",
+ "//////////8BQg0KC29uZW9mX2ZpZWxkIrsBChJOZXN0ZWRUZXN0QWxsVHlw",
+ "ZXMSNAoFY2hpbGQYASABKAsyJS5wcm90b2J1Zl91bml0dGVzdC5OZXN0ZWRU",
+ "ZXN0QWxsVHlwZXMSMAoHcGF5bG9hZBgCIAEoCzIfLnByb3RvYnVmX3VuaXR0",
+ "ZXN0LlRlc3RBbGxUeXBlcxI9Cg5yZXBlYXRlZF9jaGlsZBgDIAMoCzIlLnBy",
+ "b3RvYnVmX3VuaXR0ZXN0Lk5lc3RlZFRlc3RBbGxUeXBlcyI0ChRUZXN0RGVw",
+ "cmVjYXRlZEZpZWxkcxIcChBkZXByZWNhdGVkX2ludDMyGAEgASgFQgIYASIb",
+ "Cg5Gb3JlaWduTWVzc2FnZRIJCgFjGAEgASgFIjAKElRlc3RSZXNlcnZlZEZp",
+ "ZWxkc0oECAIQA0oECA8QEEoECAkQDFIDYmFyUgNiYXoiWgoRVGVzdEZvcmVp",
+ "Z25OZXN0ZWQSRQoOZm9yZWlnbl9uZXN0ZWQYASABKAsyLS5wcm90b2J1Zl91",
+ "bml0dGVzdC5UZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZSI0ChhUZXN0UmVh",
+ "bGx5TGFyZ2VUYWdOdW1iZXISCQoBYRgBIAEoBRINCgJiYhj///9/IAEoBSJV",
+ "ChRUZXN0UmVjdXJzaXZlTWVzc2FnZRIyCgFhGAEgASgLMicucHJvdG9idWZf",
+ "dW5pdHRlc3QuVGVzdFJlY3Vyc2l2ZU1lc3NhZ2USCQoBaRgCIAEoBSJLChRU",
+ "ZXN0TXV0dWFsUmVjdXJzaW9uQRIzCgJiYhgBIAEoCzInLnByb3RvYnVmX3Vu",
+ "aXR0ZXN0LlRlc3RNdXR1YWxSZWN1cnNpb25CImIKFFRlc3RNdXR1YWxSZWN1",
+ "cnNpb25CEjIKAWEYASABKAsyJy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TXV0",
+ "dWFsUmVjdXJzaW9uQRIWCg5vcHRpb25hbF9pbnQzMhgCIAEoBSLrAgoXVGVz",
+ "dENhbWVsQ2FzZUZpZWxkTmFtZXMSFgoOUHJpbWl0aXZlRmllbGQYASABKAUS",
+ "EwoLU3RyaW5nRmllbGQYAiABKAkSMQoJRW51bUZpZWxkGAMgASgOMh4ucHJv",
+ "dG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW0SNwoMTWVzc2FnZUZpZWxkGAQg",
+ "ASgLMiEucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2USHgoWUmVw",
+ "ZWF0ZWRQcmltaXRpdmVGaWVsZBgHIAMoBRIbChNSZXBlYXRlZFN0cmluZ0Zp",
+ "ZWxkGAggAygJEjkKEVJlcGVhdGVkRW51bUZpZWxkGAkgAygOMh4ucHJvdG9i",
+ "dWZfdW5pdHRlc3QuRm9yZWlnbkVudW0SPwoUUmVwZWF0ZWRNZXNzYWdlRmll",
+ "bGQYCiADKAsyIS5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZSLH",
+ "AQoSVGVzdEZpZWxkT3JkZXJpbmdzEhEKCW15X3N0cmluZxgLIAEoCRIOCgZt",
+ "eV9pbnQYASABKAMSEAoIbXlfZmxvYXQYZSABKAISUwoVc2luZ2xlX25lc3Rl",
+ "ZF9tZXNzYWdlGMgBIAEoCzIzLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RGaWVs",
+ "ZE9yZGVyaW5ncy5OZXN0ZWRNZXNzYWdlGicKDU5lc3RlZE1lc3NhZ2USCgoC",
+ "b28YAiABKAMSCgoCYmIYASABKAUiSwoRU3BhcnNlRW51bU1lc3NhZ2USNgoL",
+ "c3BhcnNlX2VudW0YASABKA4yIS5wcm90b2J1Zl91bml0dGVzdC5UZXN0U3Bh",
+ "cnNlRW51bSIZCglPbmVTdHJpbmcSDAoEZGF0YRgBIAEoCSIaCgpNb3JlU3Ry",
+ "aW5nEgwKBGRhdGEYASADKAkiGAoIT25lQnl0ZXMSDAoEZGF0YRgBIAEoDCIZ",
+ "CglNb3JlQnl0ZXMSDAoEZGF0YRgBIAEoDCIcCgxJbnQzMk1lc3NhZ2USDAoE",
+ "ZGF0YRgBIAEoBSIdCg1VaW50MzJNZXNzYWdlEgwKBGRhdGEYASABKA0iHAoM",
+ "SW50NjRNZXNzYWdlEgwKBGRhdGEYASABKAMiHQoNVWludDY0TWVzc2FnZRIM",
+ "CgRkYXRhGAEgASgEIhsKC0Jvb2xNZXNzYWdlEgwKBGRhdGEYASABKAgicwoJ",
+ "VGVzdE9uZW9mEhEKB2Zvb19pbnQYASABKAVIABIUCgpmb29fc3RyaW5nGAIg",
+ "ASgJSAASNgoLZm9vX21lc3NhZ2UYAyABKAsyHy5wcm90b2J1Zl91bml0dGVz",
+ "dC5UZXN0QWxsVHlwZXNIAEIFCgNmb28iqgMKD1Rlc3RQYWNrZWRUeXBlcxIY",
+ "CgxwYWNrZWRfaW50MzIYWiADKAVCAhABEhgKDHBhY2tlZF9pbnQ2NBhbIAMo",
+ "A0ICEAESGQoNcGFja2VkX3VpbnQzMhhcIAMoDUICEAESGQoNcGFja2VkX3Vp",
+ "bnQ2NBhdIAMoBEICEAESGQoNcGFja2VkX3NpbnQzMhheIAMoEUICEAESGQoN",
+ "cGFja2VkX3NpbnQ2NBhfIAMoEkICEAESGgoOcGFja2VkX2ZpeGVkMzIYYCAD",
+ "KAdCAhABEhoKDnBhY2tlZF9maXhlZDY0GGEgAygGQgIQARIbCg9wYWNrZWRf",
+ "c2ZpeGVkMzIYYiADKA9CAhABEhsKD3BhY2tlZF9zZml4ZWQ2NBhjIAMoEEIC",
+ "EAESGAoMcGFja2VkX2Zsb2F0GGQgAygCQgIQARIZCg1wYWNrZWRfZG91Ymxl",
+ "GGUgAygBQgIQARIXCgtwYWNrZWRfYm9vbBhmIAMoCEICEAESNwoLcGFja2Vk",
+ "X2VudW0YZyADKA4yHi5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUIC",
+ "EAEiyAMKEVRlc3RVbnBhY2tlZFR5cGVzEhoKDnVucGFja2VkX2ludDMyGFog",
+ "AygFQgIQABIaCg51bnBhY2tlZF9pbnQ2NBhbIAMoA0ICEAASGwoPdW5wYWNr",
+ "ZWRfdWludDMyGFwgAygNQgIQABIbCg91bnBhY2tlZF91aW50NjQYXSADKARC",
+ "AhAAEhsKD3VucGFja2VkX3NpbnQzMhheIAMoEUICEAASGwoPdW5wYWNrZWRf",
+ "c2ludDY0GF8gAygSQgIQABIcChB1bnBhY2tlZF9maXhlZDMyGGAgAygHQgIQ",
+ "ABIcChB1bnBhY2tlZF9maXhlZDY0GGEgAygGQgIQABIdChF1bnBhY2tlZF9z",
+ "Zml4ZWQzMhhiIAMoD0ICEAASHQoRdW5wYWNrZWRfc2ZpeGVkNjQYYyADKBBC",
+ "AhAAEhoKDnVucGFja2VkX2Zsb2F0GGQgAygCQgIQABIbCg91bnBhY2tlZF9k",
+ "b3VibGUYZSADKAFCAhAAEhkKDXVucGFja2VkX2Jvb2wYZiADKAhCAhAAEjkK",
+ "DXVucGFja2VkX2VudW0YZyADKA4yHi5wcm90b2J1Zl91bml0dGVzdC5Gb3Jl",
+ "aWduRW51bUICEAAiwAEKI1Rlc3RSZXBlYXRlZFNjYWxhckRpZmZlcmVudFRh",
+ "Z1NpemVzEhgKEHJlcGVhdGVkX2ZpeGVkMzIYDCADKAcSFgoOcmVwZWF0ZWRf",
+ "aW50MzIYDSADKAUSGQoQcmVwZWF0ZWRfZml4ZWQ2NBj+DyADKAYSFwoOcmVw",
+ "ZWF0ZWRfaW50NjQY/w8gAygDEhgKDnJlcGVhdGVkX2Zsb2F0GP7/DyADKAIS",
+ "GQoPcmVwZWF0ZWRfdWludDY0GP//DyADKAQiKAobVGVzdENvbW1lbnRJbmpl",
+ "Y3Rpb25NZXNzYWdlEgkKAWEYASABKAkiDAoKRm9vUmVxdWVzdCINCgtGb29S",
+ "ZXNwb25zZSISChBGb29DbGllbnRNZXNzYWdlIhIKEEZvb1NlcnZlck1lc3Nh",
+ "Z2UiDAoKQmFyUmVxdWVzdCINCgtCYXJSZXNwb25zZSpZCgtGb3JlaWduRW51",
+ "bRIXChNGT1JFSUdOX1VOU1BFQ0lGSUVEEAASDwoLRk9SRUlHTl9GT08QBBIP",
+ "CgtGT1JFSUdOX0JBUhAFEg8KC0ZPUkVJR05fQkFaEAYqdQoUVGVzdEVudW1X",
+ "aXRoRHVwVmFsdWUSKAokVEVTVF9FTlVNX1dJVEhfRFVQX1ZBTFVFX1VOU1BF",
+ "Q0lGSUVEEAASCAoERk9PMRABEggKBEJBUjEQAhIHCgNCQVoQAxIICgRGT08y",
+ "EAESCAoEQkFSMhACGgIQASqdAQoOVGVzdFNwYXJzZUVudW0SIAocVEVTVF9T",
+ "UEFSU0VfRU5VTV9VTlNQRUNJRklFRBAAEgwKCFNQQVJTRV9BEHsSDgoIU1BB",
+ "UlNFX0IQpucDEg8KCFNQQVJTRV9DELKxgAYSFQoIU1BBUlNFX0QQ8f//////",
+ "////ARIVCghTUEFSU0VfRRC03vz///////8BEgwKCFNQQVJTRV9HEAIymQEK",
+ "C1Rlc3RTZXJ2aWNlEkQKA0ZvbxIdLnByb3RvYnVmX3VuaXR0ZXN0LkZvb1Jl",
+ "cXVlc3QaHi5wcm90b2J1Zl91bml0dGVzdC5Gb29SZXNwb25zZRJECgNCYXIS",
+ "HS5wcm90b2J1Zl91bml0dGVzdC5CYXJSZXF1ZXN0Gh4ucHJvdG9idWZfdW5p",
+ "dHRlc3QuQmFyUmVzcG9uc2VCOkINVW5pdHRlc3RQcm90b0gBgAEBiAEBkAEB",
"+AEBqgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw=="));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportProto3.Descriptor, },
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
index 16634e03..5a7c4489 100644
--- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
+++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
@@ -21,141 +21,141 @@ namespace Google.Protobuf.TestProtos {
static UnittestWellKnownTypes() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "Ci9nb29nbGUvcHJvdG9idWYvdW5pdHRlc3Rfd2VsbF9rbm93bl90eXBlcy5w",
- "cm90bxIRcHJvdG9idWZfdW5pdHRlc3QaGWdvb2dsZS9wcm90b2J1Zi9hbnku",
- "cHJvdG8aGWdvb2dsZS9wcm90b2J1Zi9hcGkucHJvdG8aHmdvb2dsZS9wcm90",
- "b2J1Zi9kdXJhdGlvbi5wcm90bxobZ29vZ2xlL3Byb3RvYnVmL2VtcHR5LnBy",
- "b3RvGiBnb29nbGUvcHJvdG9idWYvZmllbGRfbWFzay5wcm90bxokZ29vZ2xl",
- "L3Byb3RvYnVmL3NvdXJjZV9jb250ZXh0LnByb3RvGhxnb29nbGUvcHJvdG9i",
- "dWYvc3RydWN0LnByb3RvGh9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1wLnBy",
- "b3RvGhpnb29nbGUvcHJvdG9idWYvdHlwZS5wcm90bxoeZ29vZ2xlL3Byb3Rv",
- "YnVmL3dyYXBwZXJzLnByb3RvIpEHChJUZXN0V2VsbEtub3duVHlwZXMSJwoJ",
- "YW55X2ZpZWxkGAEgASgLMhQuZ29vZ2xlLnByb3RvYnVmLkFueRInCglhcGlf",
- "ZmllbGQYAiABKAsyFC5nb29nbGUucHJvdG9idWYuQXBpEjEKDmR1cmF0aW9u",
- "X2ZpZWxkGAMgASgLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEisKC2Vt",
- "cHR5X2ZpZWxkGAQgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5EjQKEGZp",
- "ZWxkX21hc2tfZmllbGQYBSABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRN",
- "YXNrEjwKFHNvdXJjZV9jb250ZXh0X2ZpZWxkGAYgASgLMh4uZ29vZ2xlLnBy",
- "b3RvYnVmLlNvdXJjZUNvbnRleHQSLQoMc3RydWN0X2ZpZWxkGAcgASgLMhcu",
- "Z29vZ2xlLnByb3RvYnVmLlN0cnVjdBIzCg90aW1lc3RhbXBfZmllbGQYCCAB",
- "KAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEikKCnR5cGVfZmllbGQY",
- "CSABKAsyFS5nb29nbGUucHJvdG9idWYuVHlwZRIyCgxkb3VibGVfZmllbGQY",
- "CiABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSMAoLZmxvYXRf",
- "ZmllbGQYCyABKAsyGy5nb29nbGUucHJvdG9idWYuRmxvYXRWYWx1ZRIwCgtp",
- "bnQ2NF9maWVsZBgMIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVl",
- "EjIKDHVpbnQ2NF9maWVsZBgNIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50",
- "NjRWYWx1ZRIwCgtpbnQzMl9maWVsZBgOIAEoCzIbLmdvb2dsZS5wcm90b2J1",
- "Zi5JbnQzMlZhbHVlEjIKDHVpbnQzMl9maWVsZBgPIAEoCzIcLmdvb2dsZS5w",
- "cm90b2J1Zi5VSW50MzJWYWx1ZRIuCgpib29sX2ZpZWxkGBAgASgLMhouZ29v",
- "Z2xlLnByb3RvYnVmLkJvb2xWYWx1ZRIyCgxzdHJpbmdfZmllbGQYESABKAsy",
- "HC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUSMAoLYnl0ZXNfZmllbGQY",
- "EiABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZSKVBwoWUmVwZWF0",
- "ZWRXZWxsS25vd25UeXBlcxInCglhbnlfZmllbGQYASADKAsyFC5nb29nbGUu",
- "cHJvdG9idWYuQW55EicKCWFwaV9maWVsZBgCIAMoCzIULmdvb2dsZS5wcm90",
- "b2J1Zi5BcGkSMQoOZHVyYXRpb25fZmllbGQYAyADKAsyGS5nb29nbGUucHJv",
- "dG9idWYuRHVyYXRpb24SKwoLZW1wdHlfZmllbGQYBCADKAsyFi5nb29nbGUu",
- "cHJvdG9idWYuRW1wdHkSNAoQZmllbGRfbWFza19maWVsZBgFIAMoCzIaLmdv",
- "b2dsZS5wcm90b2J1Zi5GaWVsZE1hc2sSPAoUc291cmNlX2NvbnRleHRfZmll",
- "bGQYBiADKAsyHi5nb29nbGUucHJvdG9idWYuU291cmNlQ29udGV4dBItCgxz",
- "dHJ1Y3RfZmllbGQYByADKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0EjMK",
- "D3RpbWVzdGFtcF9maWVsZBgIIAMoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1l",
- "c3RhbXASKQoKdHlwZV9maWVsZBgJIAMoCzIVLmdvb2dsZS5wcm90b2J1Zi5U",
- "eXBlEjIKDGRvdWJsZV9maWVsZBgKIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5E",
- "b3VibGVWYWx1ZRIwCgtmbG9hdF9maWVsZBgLIAMoCzIbLmdvb2dsZS5wcm90",
- "b2J1Zi5GbG9hdFZhbHVlEjAKC2ludDY0X2ZpZWxkGAwgAygLMhsuZ29vZ2xl",
- "LnByb3RvYnVmLkludDY0VmFsdWUSMgoMdWludDY0X2ZpZWxkGA0gAygLMhwu",
- "Z29vZ2xlLnByb3RvYnVmLlVJbnQ2NFZhbHVlEjAKC2ludDMyX2ZpZWxkGA4g",
- "AygLMhsuZ29vZ2xlLnByb3RvYnVmLkludDMyVmFsdWUSMgoMdWludDMyX2Zp",
- "ZWxkGA8gAygLMhwuZ29vZ2xlLnByb3RvYnVmLlVJbnQzMlZhbHVlEi4KCmJv",
- "b2xfZmllbGQYECADKAsyGi5nb29nbGUucHJvdG9idWYuQm9vbFZhbHVlEjIK",
- "DHN0cmluZ19maWVsZBgRIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5TdHJpbmdW",
- "YWx1ZRIwCgtieXRlc19maWVsZBgSIAMoCzIbLmdvb2dsZS5wcm90b2J1Zi5C",
- "eXRlc1ZhbHVlIsUHChNPbmVvZldlbGxLbm93blR5cGVzEikKCWFueV9maWVs",
- "ZBgBIAEoCzIULmdvb2dsZS5wcm90b2J1Zi5BbnlIABIpCglhcGlfZmllbGQY",
- "AiABKAsyFC5nb29nbGUucHJvdG9idWYuQXBpSAASMwoOZHVyYXRpb25fZmll",
- "bGQYAyABKAsyGS5nb29nbGUucHJvdG9idWYuRHVyYXRpb25IABItCgtlbXB0",
- "eV9maWVsZBgEIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eUgAEjYKEGZp",
- "ZWxkX21hc2tfZmllbGQYBSABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRN",
- "YXNrSAASPgoUc291cmNlX2NvbnRleHRfZmllbGQYBiABKAsyHi5nb29nbGUu",
- "cHJvdG9idWYuU291cmNlQ29udGV4dEgAEi8KDHN0cnVjdF9maWVsZBgHIAEo",
- "CzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIABI1Cg90aW1lc3RhbXBfZmll",
- "bGQYCCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wSAASKwoKdHlw",
- "ZV9maWVsZBgJIAEoCzIVLmdvb2dsZS5wcm90b2J1Zi5UeXBlSAASNAoMZG91",
- "YmxlX2ZpZWxkGAogASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVl",
- "SAASMgoLZmxvYXRfZmllbGQYCyABKAsyGy5nb29nbGUucHJvdG9idWYuRmxv",
- "YXRWYWx1ZUgAEjIKC2ludDY0X2ZpZWxkGAwgASgLMhsuZ29vZ2xlLnByb3Rv",
- "YnVmLkludDY0VmFsdWVIABI0Cgx1aW50NjRfZmllbGQYDSABKAsyHC5nb29n",
- "bGUucHJvdG9idWYuVUludDY0VmFsdWVIABIyCgtpbnQzMl9maWVsZBgOIAEo",
- "CzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVlSAASNAoMdWludDMyX2Zp",
- "ZWxkGA8gASgLMhwuZ29vZ2xlLnByb3RvYnVmLlVJbnQzMlZhbHVlSAASMAoK",
- "Ym9vbF9maWVsZBgQIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5Cb29sVmFsdWVI",
- "ABI0CgxzdHJpbmdfZmllbGQYESABKAsyHC5nb29nbGUucHJvdG9idWYuU3Ry",
- "aW5nVmFsdWVIABIyCgtieXRlc19maWVsZBgSIAEoCzIbLmdvb2dsZS5wcm90",
- "b2J1Zi5CeXRlc1ZhbHVlSABCDQoLb25lb2ZfZmllbGQilhYKEU1hcFdlbGxL",
- "bm93blR5cGVzEkUKCWFueV9maWVsZBgBIAMoCzIyLnByb3RvYnVmX3VuaXR0",
- "ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkFueUZpZWxkRW50cnkSRQoJYXBpX2Zp",
- "ZWxkGAIgAygLMjIucHJvdG9idWZfdW5pdHRlc3QuTWFwV2VsbEtub3duVHlw",
- "ZXMuQXBpRmllbGRFbnRyeRJPCg5kdXJhdGlvbl9maWVsZBgDIAMoCzI3LnBy",
- "b3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkR1cmF0aW9uRmll",
- "bGRFbnRyeRJJCgtlbXB0eV9maWVsZBgEIAMoCzI0LnByb3RvYnVmX3VuaXR0",
- "ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkVtcHR5RmllbGRFbnRyeRJSChBmaWVs",
- "ZF9tYXNrX2ZpZWxkGAUgAygLMjgucHJvdG9idWZfdW5pdHRlc3QuTWFwV2Vs",
- "bEtub3duVHlwZXMuRmllbGRNYXNrRmllbGRFbnRyeRJaChRzb3VyY2VfY29u",
- "dGV4dF9maWVsZBgGIAMoCzI8LnByb3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxL",
- "bm93blR5cGVzLlNvdXJjZUNvbnRleHRGaWVsZEVudHJ5EksKDHN0cnVjdF9m",
- "aWVsZBgHIAMoCzI1LnByb3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5",
- "cGVzLlN0cnVjdEZpZWxkRW50cnkSUQoPdGltZXN0YW1wX2ZpZWxkGAggAygL",
- "MjgucHJvdG9idWZfdW5pdHRlc3QuTWFwV2VsbEtub3duVHlwZXMuVGltZXN0",
- "YW1wRmllbGRFbnRyeRJHCgp0eXBlX2ZpZWxkGAkgAygLMjMucHJvdG9idWZf",
- "dW5pdHRlc3QuTWFwV2VsbEtub3duVHlwZXMuVHlwZUZpZWxkRW50cnkSSwoM",
- "ZG91YmxlX2ZpZWxkGAogAygLMjUucHJvdG9idWZfdW5pdHRlc3QuTWFwV2Vs",
- "bEtub3duVHlwZXMuRG91YmxlRmllbGRFbnRyeRJJCgtmbG9hdF9maWVsZBgL",
- "IAMoCzI0LnByb3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkZs",
- "b2F0RmllbGRFbnRyeRJJCgtpbnQ2NF9maWVsZBgMIAMoCzI0LnByb3RvYnVm",
- "X3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkludDY0RmllbGRFbnRyeRJL",
- "Cgx1aW50NjRfZmllbGQYDSADKAsyNS5wcm90b2J1Zl91bml0dGVzdC5NYXBX",
- "ZWxsS25vd25UeXBlcy5VaW50NjRGaWVsZEVudHJ5EkkKC2ludDMyX2ZpZWxk",
- "GA4gAygLMjQucHJvdG9idWZfdW5pdHRlc3QuTWFwV2VsbEtub3duVHlwZXMu",
- "SW50MzJGaWVsZEVudHJ5EksKDHVpbnQzMl9maWVsZBgPIAMoCzI1LnByb3Rv",
- "YnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVzLlVpbnQzMkZpZWxkRW50",
- "cnkSRwoKYm9vbF9maWVsZBgQIAMoCzIzLnByb3RvYnVmX3VuaXR0ZXN0Lk1h",
- "cFdlbGxLbm93blR5cGVzLkJvb2xGaWVsZEVudHJ5EksKDHN0cmluZ19maWVs",
- "ZBgRIAMoCzI1LnByb3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVz",
- "LlN0cmluZ0ZpZWxkRW50cnkSSQoLYnl0ZXNfZmllbGQYEiADKAsyNC5wcm90",
- "b2J1Zl91bml0dGVzdC5NYXBXZWxsS25vd25UeXBlcy5CeXRlc0ZpZWxkRW50",
- "cnkaRQoNQW55RmllbGRFbnRyeRILCgNrZXkYASABKAUSIwoFdmFsdWUYAiAB",
- "KAsyFC5nb29nbGUucHJvdG9idWYuQW55OgI4ARpFCg1BcGlGaWVsZEVudHJ5",
- "EgsKA2tleRgBIAEoBRIjCgV2YWx1ZRgCIAEoCzIULmdvb2dsZS5wcm90b2J1",
- "Zi5BcGk6AjgBGk8KEkR1cmF0aW9uRmllbGRFbnRyeRILCgNrZXkYASABKAUS",
- "KAoFdmFsdWUYAiABKAsyGS5nb29nbGUucHJvdG9idWYuRHVyYXRpb246AjgB",
- "GkkKD0VtcHR5RmllbGRFbnRyeRILCgNrZXkYASABKAUSJQoFdmFsdWUYAiAB",
- "KAsyFi5nb29nbGUucHJvdG9idWYuRW1wdHk6AjgBGlEKE0ZpZWxkTWFza0Zp",
- "ZWxkRW50cnkSCwoDa2V5GAEgASgFEikKBXZhbHVlGAIgASgLMhouZ29vZ2xl",
- "LnByb3RvYnVmLkZpZWxkTWFzazoCOAEaWQoXU291cmNlQ29udGV4dEZpZWxk",
- "RW50cnkSCwoDa2V5GAEgASgFEi0KBXZhbHVlGAIgASgLMh4uZ29vZ2xlLnBy",
- "b3RvYnVmLlNvdXJjZUNvbnRleHQ6AjgBGksKEFN0cnVjdEZpZWxkRW50cnkS",
- "CwoDa2V5GAEgASgFEiYKBXZhbHVlGAIgASgLMhcuZ29vZ2xlLnByb3RvYnVm",
- "LlN0cnVjdDoCOAEaUQoTVGltZXN0YW1wRmllbGRFbnRyeRILCgNrZXkYASAB",
- "KAUSKQoFdmFsdWUYAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1w",
- "OgI4ARpHCg5UeXBlRmllbGRFbnRyeRILCgNrZXkYASABKAUSJAoFdmFsdWUY",
- "AiABKAsyFS5nb29nbGUucHJvdG9idWYuVHlwZToCOAEaUAoQRG91YmxlRmll",
- "bGRFbnRyeRILCgNrZXkYASABKAUSKwoFdmFsdWUYAiABKAsyHC5nb29nbGUu",
- "cHJvdG9idWYuRG91YmxlVmFsdWU6AjgBGk4KD0Zsb2F0RmllbGRFbnRyeRIL",
- "CgNrZXkYASABKAUSKgoFdmFsdWUYAiABKAsyGy5nb29nbGUucHJvdG9idWYu",
- "RmxvYXRWYWx1ZToCOAEaTgoPSW50NjRGaWVsZEVudHJ5EgsKA2tleRgBIAEo",
- "BRIqCgV2YWx1ZRgCIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVl",
- "OgI4ARpQChBVaW50NjRGaWVsZEVudHJ5EgsKA2tleRgBIAEoBRIrCgV2YWx1",
- "ZRgCIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50NjRWYWx1ZToCOAEaTgoP",
- "SW50MzJGaWVsZEVudHJ5EgsKA2tleRgBIAEoBRIqCgV2YWx1ZRgCIAEoCzIb",
- "Lmdvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVlOgI4ARpQChBVaW50MzJGaWVs",
- "ZEVudHJ5EgsKA2tleRgBIAEoBRIrCgV2YWx1ZRgCIAEoCzIcLmdvb2dsZS5w",
- "cm90b2J1Zi5VSW50MzJWYWx1ZToCOAEaTAoOQm9vbEZpZWxkRW50cnkSCwoD",
- "a2V5GAEgASgFEikKBXZhbHVlGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkJv",
- "b2xWYWx1ZToCOAEaUAoQU3RyaW5nRmllbGRFbnRyeRILCgNrZXkYASABKAUS",
- "KwoFdmFsdWUYAiABKAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWU6",
- "AjgBGk4KD0J5dGVzRmllbGRFbnRyeRILCgNrZXkYASABKAUSKgoFdmFsdWUY",
- "AiABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZToCOAFCOQoYY29t",
- "Lmdvb2dsZS5wcm90b2J1Zi50ZXN0UAGqAhpHb29nbGUuUHJvdG9idWYuVGVz",
+ "Ci9nb29nbGUvcHJvdG9idWYvdW5pdHRlc3Rfd2VsbF9rbm93bl90eXBlcy5w",
+ "cm90bxIRcHJvdG9idWZfdW5pdHRlc3QaGWdvb2dsZS9wcm90b2J1Zi9hbnku",
+ "cHJvdG8aGWdvb2dsZS9wcm90b2J1Zi9hcGkucHJvdG8aHmdvb2dsZS9wcm90",
+ "b2J1Zi9kdXJhdGlvbi5wcm90bxobZ29vZ2xlL3Byb3RvYnVmL2VtcHR5LnBy",
+ "b3RvGiBnb29nbGUvcHJvdG9idWYvZmllbGRfbWFzay5wcm90bxokZ29vZ2xl",
+ "L3Byb3RvYnVmL3NvdXJjZV9jb250ZXh0LnByb3RvGhxnb29nbGUvcHJvdG9i",
+ "dWYvc3RydWN0LnByb3RvGh9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1wLnBy",
+ "b3RvGhpnb29nbGUvcHJvdG9idWYvdHlwZS5wcm90bxoeZ29vZ2xlL3Byb3Rv",
+ "YnVmL3dyYXBwZXJzLnByb3RvIpEHChJUZXN0V2VsbEtub3duVHlwZXMSJwoJ",
+ "YW55X2ZpZWxkGAEgASgLMhQuZ29vZ2xlLnByb3RvYnVmLkFueRInCglhcGlf",
+ "ZmllbGQYAiABKAsyFC5nb29nbGUucHJvdG9idWYuQXBpEjEKDmR1cmF0aW9u",
+ "X2ZpZWxkGAMgASgLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEisKC2Vt",
+ "cHR5X2ZpZWxkGAQgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5EjQKEGZp",
+ "ZWxkX21hc2tfZmllbGQYBSABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRN",
+ "YXNrEjwKFHNvdXJjZV9jb250ZXh0X2ZpZWxkGAYgASgLMh4uZ29vZ2xlLnBy",
+ "b3RvYnVmLlNvdXJjZUNvbnRleHQSLQoMc3RydWN0X2ZpZWxkGAcgASgLMhcu",
+ "Z29vZ2xlLnByb3RvYnVmLlN0cnVjdBIzCg90aW1lc3RhbXBfZmllbGQYCCAB",
+ "KAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEikKCnR5cGVfZmllbGQY",
+ "CSABKAsyFS5nb29nbGUucHJvdG9idWYuVHlwZRIyCgxkb3VibGVfZmllbGQY",
+ "CiABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSMAoLZmxvYXRf",
+ "ZmllbGQYCyABKAsyGy5nb29nbGUucHJvdG9idWYuRmxvYXRWYWx1ZRIwCgtp",
+ "bnQ2NF9maWVsZBgMIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVl",
+ "EjIKDHVpbnQ2NF9maWVsZBgNIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50",
+ "NjRWYWx1ZRIwCgtpbnQzMl9maWVsZBgOIAEoCzIbLmdvb2dsZS5wcm90b2J1",
+ "Zi5JbnQzMlZhbHVlEjIKDHVpbnQzMl9maWVsZBgPIAEoCzIcLmdvb2dsZS5w",
+ "cm90b2J1Zi5VSW50MzJWYWx1ZRIuCgpib29sX2ZpZWxkGBAgASgLMhouZ29v",
+ "Z2xlLnByb3RvYnVmLkJvb2xWYWx1ZRIyCgxzdHJpbmdfZmllbGQYESABKAsy",
+ "HC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUSMAoLYnl0ZXNfZmllbGQY",
+ "EiABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZSKVBwoWUmVwZWF0",
+ "ZWRXZWxsS25vd25UeXBlcxInCglhbnlfZmllbGQYASADKAsyFC5nb29nbGUu",
+ "cHJvdG9idWYuQW55EicKCWFwaV9maWVsZBgCIAMoCzIULmdvb2dsZS5wcm90",
+ "b2J1Zi5BcGkSMQoOZHVyYXRpb25fZmllbGQYAyADKAsyGS5nb29nbGUucHJv",
+ "dG9idWYuRHVyYXRpb24SKwoLZW1wdHlfZmllbGQYBCADKAsyFi5nb29nbGUu",
+ "cHJvdG9idWYuRW1wdHkSNAoQZmllbGRfbWFza19maWVsZBgFIAMoCzIaLmdv",
+ "b2dsZS5wcm90b2J1Zi5GaWVsZE1hc2sSPAoUc291cmNlX2NvbnRleHRfZmll",
+ "bGQYBiADKAsyHi5nb29nbGUucHJvdG9idWYuU291cmNlQ29udGV4dBItCgxz",
+ "dHJ1Y3RfZmllbGQYByADKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0EjMK",
+ "D3RpbWVzdGFtcF9maWVsZBgIIAMoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1l",
+ "c3RhbXASKQoKdHlwZV9maWVsZBgJIAMoCzIVLmdvb2dsZS5wcm90b2J1Zi5U",
+ "eXBlEjIKDGRvdWJsZV9maWVsZBgKIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5E",
+ "b3VibGVWYWx1ZRIwCgtmbG9hdF9maWVsZBgLIAMoCzIbLmdvb2dsZS5wcm90",
+ "b2J1Zi5GbG9hdFZhbHVlEjAKC2ludDY0X2ZpZWxkGAwgAygLMhsuZ29vZ2xl",
+ "LnByb3RvYnVmLkludDY0VmFsdWUSMgoMdWludDY0X2ZpZWxkGA0gAygLMhwu",
+ "Z29vZ2xlLnByb3RvYnVmLlVJbnQ2NFZhbHVlEjAKC2ludDMyX2ZpZWxkGA4g",
+ "AygLMhsuZ29vZ2xlLnByb3RvYnVmLkludDMyVmFsdWUSMgoMdWludDMyX2Zp",
+ "ZWxkGA8gAygLMhwuZ29vZ2xlLnByb3RvYnVmLlVJbnQzMlZhbHVlEi4KCmJv",
+ "b2xfZmllbGQYECADKAsyGi5nb29nbGUucHJvdG9idWYuQm9vbFZhbHVlEjIK",
+ "DHN0cmluZ19maWVsZBgRIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5TdHJpbmdW",
+ "YWx1ZRIwCgtieXRlc19maWVsZBgSIAMoCzIbLmdvb2dsZS5wcm90b2J1Zi5C",
+ "eXRlc1ZhbHVlIsUHChNPbmVvZldlbGxLbm93blR5cGVzEikKCWFueV9maWVs",
+ "ZBgBIAEoCzIULmdvb2dsZS5wcm90b2J1Zi5BbnlIABIpCglhcGlfZmllbGQY",
+ "AiABKAsyFC5nb29nbGUucHJvdG9idWYuQXBpSAASMwoOZHVyYXRpb25fZmll",
+ "bGQYAyABKAsyGS5nb29nbGUucHJvdG9idWYuRHVyYXRpb25IABItCgtlbXB0",
+ "eV9maWVsZBgEIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eUgAEjYKEGZp",
+ "ZWxkX21hc2tfZmllbGQYBSABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRN",
+ "YXNrSAASPgoUc291cmNlX2NvbnRleHRfZmllbGQYBiABKAsyHi5nb29nbGUu",
+ "cHJvdG9idWYuU291cmNlQ29udGV4dEgAEi8KDHN0cnVjdF9maWVsZBgHIAEo",
+ "CzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIABI1Cg90aW1lc3RhbXBfZmll",
+ "bGQYCCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wSAASKwoKdHlw",
+ "ZV9maWVsZBgJIAEoCzIVLmdvb2dsZS5wcm90b2J1Zi5UeXBlSAASNAoMZG91",
+ "YmxlX2ZpZWxkGAogASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVl",
+ "SAASMgoLZmxvYXRfZmllbGQYCyABKAsyGy5nb29nbGUucHJvdG9idWYuRmxv",
+ "YXRWYWx1ZUgAEjIKC2ludDY0X2ZpZWxkGAwgASgLMhsuZ29vZ2xlLnByb3Rv",
+ "YnVmLkludDY0VmFsdWVIABI0Cgx1aW50NjRfZmllbGQYDSABKAsyHC5nb29n",
+ "bGUucHJvdG9idWYuVUludDY0VmFsdWVIABIyCgtpbnQzMl9maWVsZBgOIAEo",
+ "CzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVlSAASNAoMdWludDMyX2Zp",
+ "ZWxkGA8gASgLMhwuZ29vZ2xlLnByb3RvYnVmLlVJbnQzMlZhbHVlSAASMAoK",
+ "Ym9vbF9maWVsZBgQIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5Cb29sVmFsdWVI",
+ "ABI0CgxzdHJpbmdfZmllbGQYESABKAsyHC5nb29nbGUucHJvdG9idWYuU3Ry",
+ "aW5nVmFsdWVIABIyCgtieXRlc19maWVsZBgSIAEoCzIbLmdvb2dsZS5wcm90",
+ "b2J1Zi5CeXRlc1ZhbHVlSABCDQoLb25lb2ZfZmllbGQilhYKEU1hcFdlbGxL",
+ "bm93blR5cGVzEkUKCWFueV9maWVsZBgBIAMoCzIyLnByb3RvYnVmX3VuaXR0",
+ "ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkFueUZpZWxkRW50cnkSRQoJYXBpX2Zp",
+ "ZWxkGAIgAygLMjIucHJvdG9idWZfdW5pdHRlc3QuTWFwV2VsbEtub3duVHlw",
+ "ZXMuQXBpRmllbGRFbnRyeRJPCg5kdXJhdGlvbl9maWVsZBgDIAMoCzI3LnBy",
+ "b3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkR1cmF0aW9uRmll",
+ "bGRFbnRyeRJJCgtlbXB0eV9maWVsZBgEIAMoCzI0LnByb3RvYnVmX3VuaXR0",
+ "ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkVtcHR5RmllbGRFbnRyeRJSChBmaWVs",
+ "ZF9tYXNrX2ZpZWxkGAUgAygLMjgucHJvdG9idWZfdW5pdHRlc3QuTWFwV2Vs",
+ "bEtub3duVHlwZXMuRmllbGRNYXNrRmllbGRFbnRyeRJaChRzb3VyY2VfY29u",
+ "dGV4dF9maWVsZBgGIAMoCzI8LnByb3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxL",
+ "bm93blR5cGVzLlNvdXJjZUNvbnRleHRGaWVsZEVudHJ5EksKDHN0cnVjdF9m",
+ "aWVsZBgHIAMoCzI1LnByb3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5",
+ "cGVzLlN0cnVjdEZpZWxkRW50cnkSUQoPdGltZXN0YW1wX2ZpZWxkGAggAygL",
+ "MjgucHJvdG9idWZfdW5pdHRlc3QuTWFwV2VsbEtub3duVHlwZXMuVGltZXN0",
+ "YW1wRmllbGRFbnRyeRJHCgp0eXBlX2ZpZWxkGAkgAygLMjMucHJvdG9idWZf",
+ "dW5pdHRlc3QuTWFwV2VsbEtub3duVHlwZXMuVHlwZUZpZWxkRW50cnkSSwoM",
+ "ZG91YmxlX2ZpZWxkGAogAygLMjUucHJvdG9idWZfdW5pdHRlc3QuTWFwV2Vs",
+ "bEtub3duVHlwZXMuRG91YmxlRmllbGRFbnRyeRJJCgtmbG9hdF9maWVsZBgL",
+ "IAMoCzI0LnByb3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkZs",
+ "b2F0RmllbGRFbnRyeRJJCgtpbnQ2NF9maWVsZBgMIAMoCzI0LnByb3RvYnVm",
+ "X3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkludDY0RmllbGRFbnRyeRJL",
+ "Cgx1aW50NjRfZmllbGQYDSADKAsyNS5wcm90b2J1Zl91bml0dGVzdC5NYXBX",
+ "ZWxsS25vd25UeXBlcy5VaW50NjRGaWVsZEVudHJ5EkkKC2ludDMyX2ZpZWxk",
+ "GA4gAygLMjQucHJvdG9idWZfdW5pdHRlc3QuTWFwV2VsbEtub3duVHlwZXMu",
+ "SW50MzJGaWVsZEVudHJ5EksKDHVpbnQzMl9maWVsZBgPIAMoCzI1LnByb3Rv",
+ "YnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVzLlVpbnQzMkZpZWxkRW50",
+ "cnkSRwoKYm9vbF9maWVsZBgQIAMoCzIzLnByb3RvYnVmX3VuaXR0ZXN0Lk1h",
+ "cFdlbGxLbm93blR5cGVzLkJvb2xGaWVsZEVudHJ5EksKDHN0cmluZ19maWVs",
+ "ZBgRIAMoCzI1LnByb3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVz",
+ "LlN0cmluZ0ZpZWxkRW50cnkSSQoLYnl0ZXNfZmllbGQYEiADKAsyNC5wcm90",
+ "b2J1Zl91bml0dGVzdC5NYXBXZWxsS25vd25UeXBlcy5CeXRlc0ZpZWxkRW50",
+ "cnkaRQoNQW55RmllbGRFbnRyeRILCgNrZXkYASABKAUSIwoFdmFsdWUYAiAB",
+ "KAsyFC5nb29nbGUucHJvdG9idWYuQW55OgI4ARpFCg1BcGlGaWVsZEVudHJ5",
+ "EgsKA2tleRgBIAEoBRIjCgV2YWx1ZRgCIAEoCzIULmdvb2dsZS5wcm90b2J1",
+ "Zi5BcGk6AjgBGk8KEkR1cmF0aW9uRmllbGRFbnRyeRILCgNrZXkYASABKAUS",
+ "KAoFdmFsdWUYAiABKAsyGS5nb29nbGUucHJvdG9idWYuRHVyYXRpb246AjgB",
+ "GkkKD0VtcHR5RmllbGRFbnRyeRILCgNrZXkYASABKAUSJQoFdmFsdWUYAiAB",
+ "KAsyFi5nb29nbGUucHJvdG9idWYuRW1wdHk6AjgBGlEKE0ZpZWxkTWFza0Zp",
+ "ZWxkRW50cnkSCwoDa2V5GAEgASgFEikKBXZhbHVlGAIgASgLMhouZ29vZ2xl",
+ "LnByb3RvYnVmLkZpZWxkTWFzazoCOAEaWQoXU291cmNlQ29udGV4dEZpZWxk",
+ "RW50cnkSCwoDa2V5GAEgASgFEi0KBXZhbHVlGAIgASgLMh4uZ29vZ2xlLnBy",
+ "b3RvYnVmLlNvdXJjZUNvbnRleHQ6AjgBGksKEFN0cnVjdEZpZWxkRW50cnkS",
+ "CwoDa2V5GAEgASgFEiYKBXZhbHVlGAIgASgLMhcuZ29vZ2xlLnByb3RvYnVm",
+ "LlN0cnVjdDoCOAEaUQoTVGltZXN0YW1wRmllbGRFbnRyeRILCgNrZXkYASAB",
+ "KAUSKQoFdmFsdWUYAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1w",
+ "OgI4ARpHCg5UeXBlRmllbGRFbnRyeRILCgNrZXkYASABKAUSJAoFdmFsdWUY",
+ "AiABKAsyFS5nb29nbGUucHJvdG9idWYuVHlwZToCOAEaUAoQRG91YmxlRmll",
+ "bGRFbnRyeRILCgNrZXkYASABKAUSKwoFdmFsdWUYAiABKAsyHC5nb29nbGUu",
+ "cHJvdG9idWYuRG91YmxlVmFsdWU6AjgBGk4KD0Zsb2F0RmllbGRFbnRyeRIL",
+ "CgNrZXkYASABKAUSKgoFdmFsdWUYAiABKAsyGy5nb29nbGUucHJvdG9idWYu",
+ "RmxvYXRWYWx1ZToCOAEaTgoPSW50NjRGaWVsZEVudHJ5EgsKA2tleRgBIAEo",
+ "BRIqCgV2YWx1ZRgCIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVl",
+ "OgI4ARpQChBVaW50NjRGaWVsZEVudHJ5EgsKA2tleRgBIAEoBRIrCgV2YWx1",
+ "ZRgCIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50NjRWYWx1ZToCOAEaTgoP",
+ "SW50MzJGaWVsZEVudHJ5EgsKA2tleRgBIAEoBRIqCgV2YWx1ZRgCIAEoCzIb",
+ "Lmdvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVlOgI4ARpQChBVaW50MzJGaWVs",
+ "ZEVudHJ5EgsKA2tleRgBIAEoBRIrCgV2YWx1ZRgCIAEoCzIcLmdvb2dsZS5w",
+ "cm90b2J1Zi5VSW50MzJWYWx1ZToCOAEaTAoOQm9vbEZpZWxkRW50cnkSCwoD",
+ "a2V5GAEgASgFEikKBXZhbHVlGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkJv",
+ "b2xWYWx1ZToCOAEaUAoQU3RyaW5nRmllbGRFbnRyeRILCgNrZXkYASABKAUS",
+ "KwoFdmFsdWUYAiABKAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWU6",
+ "AjgBGk4KD0J5dGVzRmllbGRFbnRyeRILCgNrZXkYASABKAUSKgoFdmFsdWUY",
+ "AiABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZToCOAFCOQoYY29t",
+ "Lmdvb2dsZS5wcm90b2J1Zi50ZXN0UAGqAhpHb29nbGUuUHJvdG9idWYuVGVz",
"dFByb3Rvc2IGcHJvdG8z"));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.Proto.Any.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Api.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Duration.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Empty.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.FieldMask.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.SourceContext.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Struct.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Timestamp.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Type.Descriptor, global::Google.Protobuf.WellKnownTypes.Wrappers.Descriptor, },
diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
new file mode 100644
index 00000000..0a2b8b32
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
@@ -0,0 +1,66 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+ public class AnyTest
+ {
+ [Test]
+ public void Pack()
+ {
+ var message = SampleMessages.CreateFullTestAllTypes();
+ var any = Any.Pack(message);
+ Assert.AreEqual("type.googleapis.com/protobuf_unittest.TestAllTypes", any.TypeUrl);
+ Assert.AreEqual(message.CalculateSize(), any.Value.Length);
+ }
+
+ [Test]
+ public void Unpack_WrongType()
+ {
+ var message = SampleMessages.CreateFullTestAllTypes();
+ var any = Any.Pack(message);
+ Assert.Throws<InvalidProtocolBufferException>(() => any.Unpack<TestOneof>());
+ }
+
+ [Test]
+ public void Unpack_Success()
+ {
+ var message = SampleMessages.CreateFullTestAllTypes();
+ var any = Any.Pack(message);
+ var unpacked = any.Unpack<TestAllTypes>();
+ Assert.AreEqual(message, unpacked);
+ }
+ }
+}
diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
index a17bf81c..8c680d46 100644
--- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj
+++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
@@ -118,6 +118,7 @@
<Compile Include="Reflection\SingleFieldAccessor.cs" />
<Compile Include="Preconditions.cs" />
<Compile Include="WellKnownTypes\Any.cs" />
+ <Compile Include="WellKnownTypes\AnyPartial.cs" />
<Compile Include="WellKnownTypes\Api.cs" />
<Compile Include="WellKnownTypes\Duration.cs" />
<Compile Include="WellKnownTypes\DurationPartial.cs" />
diff --git a/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs b/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs
index 759955e6..99ca4bf3 100644
--- a/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs
+++ b/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs
@@ -96,6 +96,8 @@ namespace Google.Protobuf.Reflection
return descriptor;
}
+ // dependencies contains direct dependencies and any *public* dependencies
+ // of those dependencies (transitively)... so we don't need to recurse here.
foreach (FileDescriptor dependency in dependencies)
{
dependency.DescriptorPool.descriptorsByName.TryGetValue(fullName, out result);
diff --git a/csharp/src/Google.Protobuf/Reflection/DescriptorProtoFile.cs b/csharp/src/Google.Protobuf/Reflection/DescriptorProtoFile.cs
index f9158cab..5072abe2 100644
--- a/csharp/src/Google.Protobuf/Reflection/DescriptorProtoFile.cs
+++ b/csharp/src/Google.Protobuf/Reflection/DescriptorProtoFile.cs
@@ -21,117 +21,117 @@ namespace Google.Protobuf.Reflection {
static DescriptorProtoFile() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "CiBnb29nbGUvcHJvdG9idWYvZGVzY3JpcHRvci5wcm90bxIPZ29vZ2xlLnBy",
- "b3RvYnVmIkcKEUZpbGVEZXNjcmlwdG9yU2V0EjIKBGZpbGUYASADKAsyJC5n",
- "b29nbGUucHJvdG9idWYuRmlsZURlc2NyaXB0b3JQcm90byLbAwoTRmlsZURl",
- "c2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEg8KB3BhY2thZ2UYAiABKAkS",
- "EgoKZGVwZW5kZW5jeRgDIAMoCRIZChFwdWJsaWNfZGVwZW5kZW5jeRgKIAMo",
- "BRIXCg93ZWFrX2RlcGVuZGVuY3kYCyADKAUSNgoMbWVzc2FnZV90eXBlGAQg",
- "AygLMiAuZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JQcm90bxI3CgllbnVt",
- "X3R5cGUYBSADKAsyJC5nb29nbGUucHJvdG9idWYuRW51bURlc2NyaXB0b3JQ",
- "cm90bxI4CgdzZXJ2aWNlGAYgAygLMicuZ29vZ2xlLnByb3RvYnVmLlNlcnZp",
- "Y2VEZXNjcmlwdG9yUHJvdG8SOAoJZXh0ZW5zaW9uGAcgAygLMiUuZ29vZ2xl",
- "LnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvEi0KB29wdGlvbnMYCCAB",
- "KAsyHC5nb29nbGUucHJvdG9idWYuRmlsZU9wdGlvbnMSOQoQc291cmNlX2Nv",
- "ZGVfaW5mbxgJIAEoCzIfLmdvb2dsZS5wcm90b2J1Zi5Tb3VyY2VDb2RlSW5m",
- "bxIOCgZzeW50YXgYDCABKAki8AQKD0Rlc2NyaXB0b3JQcm90bxIMCgRuYW1l",
- "GAEgASgJEjQKBWZpZWxkGAIgAygLMiUuZ29vZ2xlLnByb3RvYnVmLkZpZWxk",
- "RGVzY3JpcHRvclByb3RvEjgKCWV4dGVuc2lvbhgGIAMoCzIlLmdvb2dsZS5w",
- "cm90b2J1Zi5GaWVsZERlc2NyaXB0b3JQcm90bxI1CgtuZXN0ZWRfdHlwZRgD",
- "IAMoCzIgLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9yUHJvdG8SNwoJZW51",
- "bV90eXBlGAQgAygLMiQuZ29vZ2xlLnByb3RvYnVmLkVudW1EZXNjcmlwdG9y",
- "UHJvdG8SSAoPZXh0ZW5zaW9uX3JhbmdlGAUgAygLMi8uZ29vZ2xlLnByb3Rv",
- "YnVmLkRlc2NyaXB0b3JQcm90by5FeHRlbnNpb25SYW5nZRI5CgpvbmVvZl9k",
- "ZWNsGAggAygLMiUuZ29vZ2xlLnByb3RvYnVmLk9uZW9mRGVzY3JpcHRvclBy",
- "b3RvEjAKB29wdGlvbnMYByABKAsyHy5nb29nbGUucHJvdG9idWYuTWVzc2Fn",
- "ZU9wdGlvbnMSRgoOcmVzZXJ2ZWRfcmFuZ2UYCSADKAsyLi5nb29nbGUucHJv",
- "dG9idWYuRGVzY3JpcHRvclByb3RvLlJlc2VydmVkUmFuZ2USFQoNcmVzZXJ2",
- "ZWRfbmFtZRgKIAMoCRosCg5FeHRlbnNpb25SYW5nZRINCgVzdGFydBgBIAEo",
- "BRILCgNlbmQYAiABKAUaKwoNUmVzZXJ2ZWRSYW5nZRINCgVzdGFydBgBIAEo",
- "BRILCgNlbmQYAiABKAUiqQUKFEZpZWxkRGVzY3JpcHRvclByb3RvEgwKBG5h",
- "bWUYASABKAkSDgoGbnVtYmVyGAMgASgFEjoKBWxhYmVsGAQgASgOMisuZ29v",
- "Z2xlLnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvLkxhYmVsEjgKBHR5",
- "cGUYBSABKA4yKi5nb29nbGUucHJvdG9idWYuRmllbGREZXNjcmlwdG9yUHJv",
- "dG8uVHlwZRIRCgl0eXBlX25hbWUYBiABKAkSEAoIZXh0ZW5kZWUYAiABKAkS",
- "FQoNZGVmYXVsdF92YWx1ZRgHIAEoCRITCgtvbmVvZl9pbmRleBgJIAEoBRIu",
- "CgdvcHRpb25zGAggASgLMh0uZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9u",
- "cyK2AgoEVHlwZRIPCgtUWVBFX0RPVUJMRRABEg4KClRZUEVfRkxPQVQQAhIO",
- "CgpUWVBFX0lOVDY0EAMSDwoLVFlQRV9VSU5UNjQQBBIOCgpUWVBFX0lOVDMy",
- "EAUSEAoMVFlQRV9GSVhFRDY0EAYSEAoMVFlQRV9GSVhFRDMyEAcSDQoJVFlQ",
- "RV9CT09MEAgSDwoLVFlQRV9TVFJJTkcQCRIOCgpUWVBFX0dST1VQEAoSEAoM",
- "VFlQRV9NRVNTQUdFEAsSDgoKVFlQRV9CWVRFUxAMEg8KC1RZUEVfVUlOVDMy",
- "EA0SDQoJVFlQRV9FTlVNEA4SEQoNVFlQRV9TRklYRUQzMhAPEhEKDVRZUEVf",
- "U0ZJWEVENjQQEBIPCgtUWVBFX1NJTlQzMhAREg8KC1RZUEVfU0lOVDY0EBIi",
- "QwoFTGFiZWwSEgoOTEFCRUxfT1BUSU9OQUwQARISCg5MQUJFTF9SRVFVSVJF",
- "RBACEhIKDkxBQkVMX1JFUEVBVEVEEAMiJAoUT25lb2ZEZXNjcmlwdG9yUHJv",
- "dG8SDAoEbmFtZRgBIAEoCSKMAQoTRW51bURlc2NyaXB0b3JQcm90bxIMCgRu",
- "YW1lGAEgASgJEjgKBXZhbHVlGAIgAygLMikuZ29vZ2xlLnByb3RvYnVmLkVu",
- "dW1WYWx1ZURlc2NyaXB0b3JQcm90bxItCgdvcHRpb25zGAMgASgLMhwuZ29v",
- "Z2xlLnByb3RvYnVmLkVudW1PcHRpb25zImwKGEVudW1WYWx1ZURlc2NyaXB0",
- "b3JQcm90bxIMCgRuYW1lGAEgASgJEg4KBm51bWJlchgCIAEoBRIyCgdvcHRp",
- "b25zGAMgASgLMiEuZ29vZ2xlLnByb3RvYnVmLkVudW1WYWx1ZU9wdGlvbnMi",
- "kAEKFlNlcnZpY2VEZXNjcmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRI2CgZt",
- "ZXRob2QYAiADKAsyJi5nb29nbGUucHJvdG9idWYuTWV0aG9kRGVzY3JpcHRv",
- "clByb3RvEjAKB29wdGlvbnMYAyABKAsyHy5nb29nbGUucHJvdG9idWYuU2Vy",
- "dmljZU9wdGlvbnMiwQEKFU1ldGhvZERlc2NyaXB0b3JQcm90bxIMCgRuYW1l",
- "GAEgASgJEhIKCmlucHV0X3R5cGUYAiABKAkSEwoLb3V0cHV0X3R5cGUYAyAB",
- "KAkSLwoHb3B0aW9ucxgEIAEoCzIeLmdvb2dsZS5wcm90b2J1Zi5NZXRob2RP",
- "cHRpb25zEh8KEGNsaWVudF9zdHJlYW1pbmcYBSABKAg6BWZhbHNlEh8KEHNl",
- "cnZlcl9zdHJlYW1pbmcYBiABKAg6BWZhbHNlIqoFCgtGaWxlT3B0aW9ucxIU",
- "CgxqYXZhX3BhY2thZ2UYASABKAkSHAoUamF2YV9vdXRlcl9jbGFzc25hbWUY",
- "CCABKAkSIgoTamF2YV9tdWx0aXBsZV9maWxlcxgKIAEoCDoFZmFsc2USLAod",
- "amF2YV9nZW5lcmF0ZV9lcXVhbHNfYW5kX2hhc2gYFCABKAg6BWZhbHNlEiUK",
- "FmphdmFfc3RyaW5nX2NoZWNrX3V0ZjgYGyABKAg6BWZhbHNlEkYKDG9wdGlt",
- "aXplX2ZvchgJIAEoDjIpLmdvb2dsZS5wcm90b2J1Zi5GaWxlT3B0aW9ucy5P",
- "cHRpbWl6ZU1vZGU6BVNQRUVEEhIKCmdvX3BhY2thZ2UYCyABKAkSIgoTY2Nf",
- "Z2VuZXJpY19zZXJ2aWNlcxgQIAEoCDoFZmFsc2USJAoVamF2YV9nZW5lcmlj",
- "X3NlcnZpY2VzGBEgASgIOgVmYWxzZRIiChNweV9nZW5lcmljX3NlcnZpY2Vz",
- "GBIgASgIOgVmYWxzZRIZCgpkZXByZWNhdGVkGBcgASgIOgVmYWxzZRIfChBj",
- "Y19lbmFibGVfYXJlbmFzGB8gASgIOgVmYWxzZRIZChFvYmpjX2NsYXNzX3By",
- "ZWZpeBgkIAEoCRIYChBjc2hhcnBfbmFtZXNwYWNlGCUgASgJEicKH2phdmFu",
- "YW5vX3VzZV9kZXByZWNhdGVkX3BhY2thZ2UYJiABKAgSQwoUdW5pbnRlcnBy",
- "ZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJw",
- "cmV0ZWRPcHRpb24iOgoMT3B0aW1pemVNb2RlEgkKBVNQRUVEEAESDQoJQ09E",
- "RV9TSVpFEAISEAoMTElURV9SVU5USU1FEAMqCQjoBxCAgICAAiLmAQoOTWVz",
- "c2FnZU9wdGlvbnMSJgoXbWVzc2FnZV9zZXRfd2lyZV9mb3JtYXQYASABKAg6",
- "BWZhbHNlEi4KH25vX3N0YW5kYXJkX2Rlc2NyaXB0b3JfYWNjZXNzb3IYAiAB",
- "KAg6BWZhbHNlEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNlEhEKCW1hcF9l",
- "bnRyeRgHIAEoCBJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5n",
- "b29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbioJCOgHEICAgIAC",
- "IpgDCgxGaWVsZE9wdGlvbnMSOgoFY3R5cGUYASABKA4yIy5nb29nbGUucHJv",
- "dG9idWYuRmllbGRPcHRpb25zLkNUeXBlOgZTVFJJTkcSDgoGcGFja2VkGAIg",
- "ASgIEj8KBmpzdHlwZRgGIAEoDjIkLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9w",
- "dGlvbnMuSlNUeXBlOglKU19OT1JNQUwSEwoEbGF6eRgFIAEoCDoFZmFsc2US",
- "GQoKZGVwcmVjYXRlZBgDIAEoCDoFZmFsc2USEwoEd2VhaxgKIAEoCDoFZmFs",
- "c2USQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnBy",
- "b3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24iLwoFQ1R5cGUSCgoGU1RSSU5H",
- "EAASCAoEQ09SRBABEhAKDFNUUklOR19QSUVDRRACIjUKBkpTVHlwZRINCglK",
- "U19OT1JNQUwQABINCglKU19TVFJJTkcQARINCglKU19OVU1CRVIQAioJCOgH",
- "EICAgIACIo0BCgtFbnVtT3B0aW9ucxITCgthbGxvd19hbGlhcxgCIAEoCBIZ",
- "CgpkZXByZWNhdGVkGAMgASgIOgVmYWxzZRJDChR1bmludGVycHJldGVkX29w",
- "dGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9w",
- "dGlvbioJCOgHEICAgIACIn0KEEVudW1WYWx1ZU9wdGlvbnMSGQoKZGVwcmVj",
- "YXRlZBgBIAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcg",
- "AygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjo",
- "BxCAgICAAiJ7Cg5TZXJ2aWNlT3B0aW9ucxIZCgpkZXByZWNhdGVkGCEgASgI",
- "OgVmYWxzZRJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29n",
- "bGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbioJCOgHEICAgIACInoK",
- "DU1ldGhvZE9wdGlvbnMSGQoKZGVwcmVjYXRlZBghIAEoCDoFZmFsc2USQwoU",
- "dW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVm",
- "LlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiKeAgoTVW5pbnRlcnBy",
- "ZXRlZE9wdGlvbhI7CgRuYW1lGAIgAygLMi0uZ29vZ2xlLnByb3RvYnVmLlVu",
- "aW50ZXJwcmV0ZWRPcHRpb24uTmFtZVBhcnQSGAoQaWRlbnRpZmllcl92YWx1",
- "ZRgDIAEoCRIaChJwb3NpdGl2ZV9pbnRfdmFsdWUYBCABKAQSGgoSbmVnYXRp",
- "dmVfaW50X3ZhbHVlGAUgASgDEhQKDGRvdWJsZV92YWx1ZRgGIAEoARIUCgxz",
- "dHJpbmdfdmFsdWUYByABKAwSFwoPYWdncmVnYXRlX3ZhbHVlGAggASgJGjMK",
- "CE5hbWVQYXJ0EhEKCW5hbWVfcGFydBgBIAIoCRIUCgxpc19leHRlbnNpb24Y",
- "AiACKAgi1QEKDlNvdXJjZUNvZGVJbmZvEjoKCGxvY2F0aW9uGAEgAygLMigu",
- "Z29vZ2xlLnByb3RvYnVmLlNvdXJjZUNvZGVJbmZvLkxvY2F0aW9uGoYBCghM",
- "b2NhdGlvbhIQCgRwYXRoGAEgAygFQgIQARIQCgRzcGFuGAIgAygFQgIQARIY",
- "ChBsZWFkaW5nX2NvbW1lbnRzGAMgASgJEhkKEXRyYWlsaW5nX2NvbW1lbnRz",
- "GAQgASgJEiEKGWxlYWRpbmdfZGV0YWNoZWRfY29tbWVudHMYBiADKAlCWwoT",
- "Y29tLmdvb2dsZS5wcm90b2J1ZkIQRGVzY3JpcHRvclByb3Rvc0gBWgpkZXNj",
- "cmlwdG9yogIDR1BCqgIaR29vZ2xlLlByb3RvYnVmLlJlZmxlY3Rpb26wAgE="));
+ "CiBnb29nbGUvcHJvdG9idWYvZGVzY3JpcHRvci5wcm90bxIPZ29vZ2xlLnBy",
+ "b3RvYnVmIkcKEUZpbGVEZXNjcmlwdG9yU2V0EjIKBGZpbGUYASADKAsyJC5n",
+ "b29nbGUucHJvdG9idWYuRmlsZURlc2NyaXB0b3JQcm90byLbAwoTRmlsZURl",
+ "c2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEg8KB3BhY2thZ2UYAiABKAkS",
+ "EgoKZGVwZW5kZW5jeRgDIAMoCRIZChFwdWJsaWNfZGVwZW5kZW5jeRgKIAMo",
+ "BRIXCg93ZWFrX2RlcGVuZGVuY3kYCyADKAUSNgoMbWVzc2FnZV90eXBlGAQg",
+ "AygLMiAuZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JQcm90bxI3CgllbnVt",
+ "X3R5cGUYBSADKAsyJC5nb29nbGUucHJvdG9idWYuRW51bURlc2NyaXB0b3JQ",
+ "cm90bxI4CgdzZXJ2aWNlGAYgAygLMicuZ29vZ2xlLnByb3RvYnVmLlNlcnZp",
+ "Y2VEZXNjcmlwdG9yUHJvdG8SOAoJZXh0ZW5zaW9uGAcgAygLMiUuZ29vZ2xl",
+ "LnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvEi0KB29wdGlvbnMYCCAB",
+ "KAsyHC5nb29nbGUucHJvdG9idWYuRmlsZU9wdGlvbnMSOQoQc291cmNlX2Nv",
+ "ZGVfaW5mbxgJIAEoCzIfLmdvb2dsZS5wcm90b2J1Zi5Tb3VyY2VDb2RlSW5m",
+ "bxIOCgZzeW50YXgYDCABKAki8AQKD0Rlc2NyaXB0b3JQcm90bxIMCgRuYW1l",
+ "GAEgASgJEjQKBWZpZWxkGAIgAygLMiUuZ29vZ2xlLnByb3RvYnVmLkZpZWxk",
+ "RGVzY3JpcHRvclByb3RvEjgKCWV4dGVuc2lvbhgGIAMoCzIlLmdvb2dsZS5w",
+ "cm90b2J1Zi5GaWVsZERlc2NyaXB0b3JQcm90bxI1CgtuZXN0ZWRfdHlwZRgD",
+ "IAMoCzIgLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9yUHJvdG8SNwoJZW51",
+ "bV90eXBlGAQgAygLMiQuZ29vZ2xlLnByb3RvYnVmLkVudW1EZXNjcmlwdG9y",
+ "UHJvdG8SSAoPZXh0ZW5zaW9uX3JhbmdlGAUgAygLMi8uZ29vZ2xlLnByb3Rv",
+ "YnVmLkRlc2NyaXB0b3JQcm90by5FeHRlbnNpb25SYW5nZRI5CgpvbmVvZl9k",
+ "ZWNsGAggAygLMiUuZ29vZ2xlLnByb3RvYnVmLk9uZW9mRGVzY3JpcHRvclBy",
+ "b3RvEjAKB29wdGlvbnMYByABKAsyHy5nb29nbGUucHJvdG9idWYuTWVzc2Fn",
+ "ZU9wdGlvbnMSRgoOcmVzZXJ2ZWRfcmFuZ2UYCSADKAsyLi5nb29nbGUucHJv",
+ "dG9idWYuRGVzY3JpcHRvclByb3RvLlJlc2VydmVkUmFuZ2USFQoNcmVzZXJ2",
+ "ZWRfbmFtZRgKIAMoCRosCg5FeHRlbnNpb25SYW5nZRINCgVzdGFydBgBIAEo",
+ "BRILCgNlbmQYAiABKAUaKwoNUmVzZXJ2ZWRSYW5nZRINCgVzdGFydBgBIAEo",
+ "BRILCgNlbmQYAiABKAUiqQUKFEZpZWxkRGVzY3JpcHRvclByb3RvEgwKBG5h",
+ "bWUYASABKAkSDgoGbnVtYmVyGAMgASgFEjoKBWxhYmVsGAQgASgOMisuZ29v",
+ "Z2xlLnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvLkxhYmVsEjgKBHR5",
+ "cGUYBSABKA4yKi5nb29nbGUucHJvdG9idWYuRmllbGREZXNjcmlwdG9yUHJv",
+ "dG8uVHlwZRIRCgl0eXBlX25hbWUYBiABKAkSEAoIZXh0ZW5kZWUYAiABKAkS",
+ "FQoNZGVmYXVsdF92YWx1ZRgHIAEoCRITCgtvbmVvZl9pbmRleBgJIAEoBRIu",
+ "CgdvcHRpb25zGAggASgLMh0uZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9u",
+ "cyK2AgoEVHlwZRIPCgtUWVBFX0RPVUJMRRABEg4KClRZUEVfRkxPQVQQAhIO",
+ "CgpUWVBFX0lOVDY0EAMSDwoLVFlQRV9VSU5UNjQQBBIOCgpUWVBFX0lOVDMy",
+ "EAUSEAoMVFlQRV9GSVhFRDY0EAYSEAoMVFlQRV9GSVhFRDMyEAcSDQoJVFlQ",
+ "RV9CT09MEAgSDwoLVFlQRV9TVFJJTkcQCRIOCgpUWVBFX0dST1VQEAoSEAoM",
+ "VFlQRV9NRVNTQUdFEAsSDgoKVFlQRV9CWVRFUxAMEg8KC1RZUEVfVUlOVDMy",
+ "EA0SDQoJVFlQRV9FTlVNEA4SEQoNVFlQRV9TRklYRUQzMhAPEhEKDVRZUEVf",
+ "U0ZJWEVENjQQEBIPCgtUWVBFX1NJTlQzMhAREg8KC1RZUEVfU0lOVDY0EBIi",
+ "QwoFTGFiZWwSEgoOTEFCRUxfT1BUSU9OQUwQARISCg5MQUJFTF9SRVFVSVJF",
+ "RBACEhIKDkxBQkVMX1JFUEVBVEVEEAMiJAoUT25lb2ZEZXNjcmlwdG9yUHJv",
+ "dG8SDAoEbmFtZRgBIAEoCSKMAQoTRW51bURlc2NyaXB0b3JQcm90bxIMCgRu",
+ "YW1lGAEgASgJEjgKBXZhbHVlGAIgAygLMikuZ29vZ2xlLnByb3RvYnVmLkVu",
+ "dW1WYWx1ZURlc2NyaXB0b3JQcm90bxItCgdvcHRpb25zGAMgASgLMhwuZ29v",
+ "Z2xlLnByb3RvYnVmLkVudW1PcHRpb25zImwKGEVudW1WYWx1ZURlc2NyaXB0",
+ "b3JQcm90bxIMCgRuYW1lGAEgASgJEg4KBm51bWJlchgCIAEoBRIyCgdvcHRp",
+ "b25zGAMgASgLMiEuZ29vZ2xlLnByb3RvYnVmLkVudW1WYWx1ZU9wdGlvbnMi",
+ "kAEKFlNlcnZpY2VEZXNjcmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRI2CgZt",
+ "ZXRob2QYAiADKAsyJi5nb29nbGUucHJvdG9idWYuTWV0aG9kRGVzY3JpcHRv",
+ "clByb3RvEjAKB29wdGlvbnMYAyABKAsyHy5nb29nbGUucHJvdG9idWYuU2Vy",
+ "dmljZU9wdGlvbnMiwQEKFU1ldGhvZERlc2NyaXB0b3JQcm90bxIMCgRuYW1l",
+ "GAEgASgJEhIKCmlucHV0X3R5cGUYAiABKAkSEwoLb3V0cHV0X3R5cGUYAyAB",
+ "KAkSLwoHb3B0aW9ucxgEIAEoCzIeLmdvb2dsZS5wcm90b2J1Zi5NZXRob2RP",
+ "cHRpb25zEh8KEGNsaWVudF9zdHJlYW1pbmcYBSABKAg6BWZhbHNlEh8KEHNl",
+ "cnZlcl9zdHJlYW1pbmcYBiABKAg6BWZhbHNlIqoFCgtGaWxlT3B0aW9ucxIU",
+ "CgxqYXZhX3BhY2thZ2UYASABKAkSHAoUamF2YV9vdXRlcl9jbGFzc25hbWUY",
+ "CCABKAkSIgoTamF2YV9tdWx0aXBsZV9maWxlcxgKIAEoCDoFZmFsc2USLAod",
+ "amF2YV9nZW5lcmF0ZV9lcXVhbHNfYW5kX2hhc2gYFCABKAg6BWZhbHNlEiUK",
+ "FmphdmFfc3RyaW5nX2NoZWNrX3V0ZjgYGyABKAg6BWZhbHNlEkYKDG9wdGlt",
+ "aXplX2ZvchgJIAEoDjIpLmdvb2dsZS5wcm90b2J1Zi5GaWxlT3B0aW9ucy5P",
+ "cHRpbWl6ZU1vZGU6BVNQRUVEEhIKCmdvX3BhY2thZ2UYCyABKAkSIgoTY2Nf",
+ "Z2VuZXJpY19zZXJ2aWNlcxgQIAEoCDoFZmFsc2USJAoVamF2YV9nZW5lcmlj",
+ "X3NlcnZpY2VzGBEgASgIOgVmYWxzZRIiChNweV9nZW5lcmljX3NlcnZpY2Vz",
+ "GBIgASgIOgVmYWxzZRIZCgpkZXByZWNhdGVkGBcgASgIOgVmYWxzZRIfChBj",
+ "Y19lbmFibGVfYXJlbmFzGB8gASgIOgVmYWxzZRIZChFvYmpjX2NsYXNzX3By",
+ "ZWZpeBgkIAEoCRIYChBjc2hhcnBfbmFtZXNwYWNlGCUgASgJEicKH2phdmFu",
+ "YW5vX3VzZV9kZXByZWNhdGVkX3BhY2thZ2UYJiABKAgSQwoUdW5pbnRlcnBy",
+ "ZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJw",
+ "cmV0ZWRPcHRpb24iOgoMT3B0aW1pemVNb2RlEgkKBVNQRUVEEAESDQoJQ09E",
+ "RV9TSVpFEAISEAoMTElURV9SVU5USU1FEAMqCQjoBxCAgICAAiLmAQoOTWVz",
+ "c2FnZU9wdGlvbnMSJgoXbWVzc2FnZV9zZXRfd2lyZV9mb3JtYXQYASABKAg6",
+ "BWZhbHNlEi4KH25vX3N0YW5kYXJkX2Rlc2NyaXB0b3JfYWNjZXNzb3IYAiAB",
+ "KAg6BWZhbHNlEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNlEhEKCW1hcF9l",
+ "bnRyeRgHIAEoCBJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5n",
+ "b29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbioJCOgHEICAgIAC",
+ "IpgDCgxGaWVsZE9wdGlvbnMSOgoFY3R5cGUYASABKA4yIy5nb29nbGUucHJv",
+ "dG9idWYuRmllbGRPcHRpb25zLkNUeXBlOgZTVFJJTkcSDgoGcGFja2VkGAIg",
+ "ASgIEj8KBmpzdHlwZRgGIAEoDjIkLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9w",
+ "dGlvbnMuSlNUeXBlOglKU19OT1JNQUwSEwoEbGF6eRgFIAEoCDoFZmFsc2US",
+ "GQoKZGVwcmVjYXRlZBgDIAEoCDoFZmFsc2USEwoEd2VhaxgKIAEoCDoFZmFs",
+ "c2USQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnBy",
+ "b3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24iLwoFQ1R5cGUSCgoGU1RSSU5H",
+ "EAASCAoEQ09SRBABEhAKDFNUUklOR19QSUVDRRACIjUKBkpTVHlwZRINCglK",
+ "U19OT1JNQUwQABINCglKU19TVFJJTkcQARINCglKU19OVU1CRVIQAioJCOgH",
+ "EICAgIACIo0BCgtFbnVtT3B0aW9ucxITCgthbGxvd19hbGlhcxgCIAEoCBIZ",
+ "CgpkZXByZWNhdGVkGAMgASgIOgVmYWxzZRJDChR1bmludGVycHJldGVkX29w",
+ "dGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9w",
+ "dGlvbioJCOgHEICAgIACIn0KEEVudW1WYWx1ZU9wdGlvbnMSGQoKZGVwcmVj",
+ "YXRlZBgBIAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcg",
+ "AygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjo",
+ "BxCAgICAAiJ7Cg5TZXJ2aWNlT3B0aW9ucxIZCgpkZXByZWNhdGVkGCEgASgI",
+ "OgVmYWxzZRJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29n",
+ "bGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbioJCOgHEICAgIACInoK",
+ "DU1ldGhvZE9wdGlvbnMSGQoKZGVwcmVjYXRlZBghIAEoCDoFZmFsc2USQwoU",
+ "dW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVm",
+ "LlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiKeAgoTVW5pbnRlcnBy",
+ "ZXRlZE9wdGlvbhI7CgRuYW1lGAIgAygLMi0uZ29vZ2xlLnByb3RvYnVmLlVu",
+ "aW50ZXJwcmV0ZWRPcHRpb24uTmFtZVBhcnQSGAoQaWRlbnRpZmllcl92YWx1",
+ "ZRgDIAEoCRIaChJwb3NpdGl2ZV9pbnRfdmFsdWUYBCABKAQSGgoSbmVnYXRp",
+ "dmVfaW50X3ZhbHVlGAUgASgDEhQKDGRvdWJsZV92YWx1ZRgGIAEoARIUCgxz",
+ "dHJpbmdfdmFsdWUYByABKAwSFwoPYWdncmVnYXRlX3ZhbHVlGAggASgJGjMK",
+ "CE5hbWVQYXJ0EhEKCW5hbWVfcGFydBgBIAIoCRIUCgxpc19leHRlbnNpb24Y",
+ "AiACKAgi1QEKDlNvdXJjZUNvZGVJbmZvEjoKCGxvY2F0aW9uGAEgAygLMigu",
+ "Z29vZ2xlLnByb3RvYnVmLlNvdXJjZUNvZGVJbmZvLkxvY2F0aW9uGoYBCghM",
+ "b2NhdGlvbhIQCgRwYXRoGAEgAygFQgIQARIQCgRzcGFuGAIgAygFQgIQARIY",
+ "ChBsZWFkaW5nX2NvbW1lbnRzGAMgASgJEhkKEXRyYWlsaW5nX2NvbW1lbnRz",
+ "GAQgASgJEiEKGWxlYWRpbmdfZGV0YWNoZWRfY29tbWVudHMYBiADKAlCWAoT",
+ "Y29tLmdvb2dsZS5wcm90b2J1ZkIQRGVzY3JpcHRvclByb3Rvc0gBWgpkZXNj",
+ "cmlwdG9yogIDR1BCqgIaR29vZ2xlLlByb3RvYnVmLlJlZmxlY3Rpb24="));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
index 204b37cf..51ff2d4e 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
@@ -23,9 +23,9 @@ namespace Google.Protobuf.WellKnownTypes {
static Any() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "Chlnb29nbGUvcHJvdG9idWYvYW55LnByb3RvEg9nb29nbGUucHJvdG9idWYi",
- "JgoDQW55EhAKCHR5cGVfdXJsGAEgASgJEg0KBXZhbHVlGAIgASgMQksKE2Nv",
- "bS5nb29nbGUucHJvdG9idWZCCEFueVByb3RvUAGgAQGiAgNHUEKqAh5Hb29n",
+ "Chlnb29nbGUvcHJvdG9idWYvYW55LnByb3RvEg9nb29nbGUucHJvdG9idWYi",
+ "JgoDQW55EhAKCHR5cGVfdXJsGAEgASgJEg0KBXZhbHVlGAIgASgMQksKE2Nv",
+ "bS5nb29nbGUucHJvdG9idWZCCEFueVByb3RvUAGgAQGiAgNHUEKqAh5Hb29n",
"bGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw=="));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { },
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs
new file mode 100644
index 00000000..082f7432
--- /dev/null
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs
@@ -0,0 +1,79 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using Google.Protobuf.Reflection;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+ public partial class Any
+ {
+ // This could be moved to MessageDescriptor if we wanted to, but keeping it here means
+ // all the Any-specific code is in the same place.
+ private static string GetTypeUrl(MessageDescriptor descriptor)
+ {
+ return "type.googleapis.com/" + descriptor.FullName;
+ }
+
+ /// <summary>
+ /// Unpacks the content of this Any message into the target message type,
+ /// which must match the type URL within this Any message.
+ /// </summary>
+ /// <typeparam name="T">The type of message to unpack the content into.</typeparam>
+ /// <returns>The unpacked message.</returns>
+ /// <exception cref="InvalidProtocolBufferException">The target message type doesn't match the type URL in this message</exception>
+ public T Unpack<T>() where T : IMessage, new()
+ {
+ // Note: this doesn't perform as well is it might. We could take a MessageParser<T> in an alternative overload,
+ // which would be expected to perform slightly better... although the difference is likely to be negligible.
+ T target = new T();
+ string targetTypeUrl = GetTypeUrl(target.Descriptor);
+ if (TypeUrl != targetTypeUrl)
+ {
+ throw new InvalidProtocolBufferException(string.Format("Type url for {0} is {1}; Any message's type url is {2}",
+ target.Descriptor.Name, targetTypeUrl, TypeUrl));
+ }
+ target.MergeFrom(Value);
+ return target;
+ }
+
+ /// <summary>
+ /// Packs the specified message into an Any message.
+ /// </summary>
+ /// <param name="message">The message to pack.</param>
+ /// <returns>An Any message with the content and type URL of <paramref name="message"/>.</returns>
+ public static Any Pack(IMessage message)
+ {
+ Preconditions.CheckNotNull(message, "message");
+ return new Any { TypeUrl = GetTypeUrl(message.Descriptor), Value = message.ToByteString() };
+ }
+ }
+}
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
index a5f95093..4d06ff35 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
@@ -23,24 +23,28 @@ namespace Google.Protobuf.WellKnownTypes {
static Api() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "Chlnb29nbGUvcHJvdG9idWYvYXBpLnByb3RvEg9nb29nbGUucHJvdG9idWYa",
- "JGdvb2dsZS9wcm90b2J1Zi9zb3VyY2VfY29udGV4dC5wcm90bxoaZ29vZ2xl",
- "L3Byb3RvYnVmL3R5cGUucHJvdG8isAEKA0FwaRIMCgRuYW1lGAEgASgJEigK",
- "B21ldGhvZHMYAiADKAsyFy5nb29nbGUucHJvdG9idWYuTWV0aG9kEigKB29w",
- "dGlvbnMYAyADKAsyFy5nb29nbGUucHJvdG9idWYuT3B0aW9uEg8KB3ZlcnNp",
- "b24YBCABKAkSNgoOc291cmNlX2NvbnRleHQYBSABKAsyHi5nb29nbGUucHJv",
- "dG9idWYuU291cmNlQ29udGV4dCKsAQoGTWV0aG9kEgwKBG5hbWUYASABKAkS",
- "GAoQcmVxdWVzdF90eXBlX3VybBgCIAEoCRIZChFyZXF1ZXN0X3N0cmVhbWlu",
- "ZxgDIAEoCBIZChFyZXNwb25zZV90eXBlX3VybBgEIAEoCRIaChJyZXNwb25z",
- "ZV9zdHJlYW1pbmcYBSABKAgSKAoHb3B0aW9ucxgGIAMoCzIXLmdvb2dsZS5w",
- "cm90b2J1Zi5PcHRpb25CSAoTY29tLmdvb2dsZS5wcm90b2J1ZkIIQXBpUHJv",
- "dG9QAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IG",
- "cHJvdG8z"));
+ "Chlnb29nbGUvcHJvdG9idWYvYXBpLnByb3RvEg9nb29nbGUucHJvdG9idWYa",
+ "JGdvb2dsZS9wcm90b2J1Zi9zb3VyY2VfY29udGV4dC5wcm90bxoaZ29vZ2xl",
+ "L3Byb3RvYnVmL3R5cGUucHJvdG8igQIKA0FwaRIMCgRuYW1lGAEgASgJEigK",
+ "B21ldGhvZHMYAiADKAsyFy5nb29nbGUucHJvdG9idWYuTWV0aG9kEigKB29w",
+ "dGlvbnMYAyADKAsyFy5nb29nbGUucHJvdG9idWYuT3B0aW9uEg8KB3ZlcnNp",
+ "b24YBCABKAkSNgoOc291cmNlX2NvbnRleHQYBSABKAsyHi5nb29nbGUucHJv",
+ "dG9idWYuU291cmNlQ29udGV4dBImCgZtaXhpbnMYBiADKAsyFi5nb29nbGUu",
+ "cHJvdG9idWYuTWl4aW4SJwoGc3ludGF4GAcgASgOMhcuZ29vZ2xlLnByb3Rv",
+ "YnVmLlN5bnRheCLVAQoGTWV0aG9kEgwKBG5hbWUYASABKAkSGAoQcmVxdWVz",
+ "dF90eXBlX3VybBgCIAEoCRIZChFyZXF1ZXN0X3N0cmVhbWluZxgDIAEoCBIZ",
+ "ChFyZXNwb25zZV90eXBlX3VybBgEIAEoCRIaChJyZXNwb25zZV9zdHJlYW1p",
+ "bmcYBSABKAgSKAoHb3B0aW9ucxgGIAMoCzIXLmdvb2dsZS5wcm90b2J1Zi5P",
+ "cHRpb24SJwoGc3ludGF4GAcgASgOMhcuZ29vZ2xlLnByb3RvYnVmLlN5bnRh",
+ "eCIjCgVNaXhpbhIMCgRuYW1lGAEgASgJEgwKBHJvb3QYAiABKAlCSwoTY29t",
+ "Lmdvb2dsZS5wcm90b2J1ZkIIQXBpUHJvdG9QAaABAaICA0dQQqoCHkdvb2ds",
+ "ZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJvdG8z"));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.Proto.SourceContext.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Type.Descriptor, },
new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
- new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Api), new[]{ "Name", "Methods", "Options", "Version", "SourceContext" }, null, null, null),
- new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Method), new[]{ "Name", "RequestTypeUrl", "RequestStreaming", "ResponseTypeUrl", "ResponseStreaming", "Options" }, null, null, null)
+ new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Api), new[]{ "Name", "Methods", "Options", "Version", "SourceContext", "Mixins", "Syntax" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Method), new[]{ "Name", "RequestTypeUrl", "RequestStreaming", "ResponseTypeUrl", "ResponseStreaming", "Options", "Syntax" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Mixin), new[]{ "Name", "Root" }, null, null, null)
}));
}
#endregion
@@ -73,6 +77,8 @@ namespace Google.Protobuf.WellKnownTypes {
options_ = other.options_.Clone();
version_ = other.version_;
SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null;
+ mixins_ = other.mixins_.Clone();
+ syntax_ = other.syntax_;
}
public Api Clone() {
@@ -122,6 +128,23 @@ namespace Google.Protobuf.WellKnownTypes {
}
}
+ public const int MixinsFieldNumber = 6;
+ private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Mixin> _repeated_mixins_codec
+ = pb::FieldCodec.ForMessage(50, global::Google.Protobuf.WellKnownTypes.Mixin.Parser);
+ private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Mixin> mixins_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Mixin>();
+ public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Mixin> Mixins {
+ get { return mixins_; }
+ }
+
+ public const int SyntaxFieldNumber = 7;
+ private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2;
+ public global::Google.Protobuf.WellKnownTypes.Syntax Syntax {
+ get { return syntax_; }
+ set {
+ syntax_ = value;
+ }
+ }
+
public override bool Equals(object other) {
return Equals(other as Api);
}
@@ -138,6 +161,8 @@ namespace Google.Protobuf.WellKnownTypes {
if(!options_.Equals(other.options_)) return false;
if (Version != other.Version) return false;
if (!object.Equals(SourceContext, other.SourceContext)) return false;
+ if(!mixins_.Equals(other.mixins_)) return false;
+ if (Syntax != other.Syntax) return false;
return true;
}
@@ -148,6 +173,8 @@ namespace Google.Protobuf.WellKnownTypes {
hash ^= options_.GetHashCode();
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();
return hash;
}
@@ -170,6 +197,11 @@ namespace Google.Protobuf.WellKnownTypes {
output.WriteRawTag(42);
output.WriteMessage(SourceContext);
}
+ mixins_.WriteTo(output, _repeated_mixins_codec);
+ if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
+ output.WriteRawTag(56);
+ output.WriteEnum((int) Syntax);
+ }
}
public int CalculateSize() {
@@ -185,6 +217,10 @@ namespace Google.Protobuf.WellKnownTypes {
if (sourceContext_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContext);
}
+ size += mixins_.CalculateSize(_repeated_mixins_codec);
+ if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
+ size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
+ }
return size;
}
@@ -206,6 +242,10 @@ namespace Google.Protobuf.WellKnownTypes {
}
SourceContext.MergeFrom(other.SourceContext);
}
+ mixins_.Add(other.mixins_);
+ if (other.Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
+ Syntax = other.Syntax;
+ }
}
public void MergeFrom(pb::CodedInputStream input) {
@@ -238,6 +278,14 @@ namespace Google.Protobuf.WellKnownTypes {
input.ReadMessage(sourceContext_);
break;
}
+ case 50: {
+ mixins_.AddEntriesFrom(input, _repeated_mixins_codec);
+ break;
+ }
+ case 56: {
+ syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
+ break;
+ }
}
}
}
@@ -270,6 +318,7 @@ namespace Google.Protobuf.WellKnownTypes {
responseTypeUrl_ = other.responseTypeUrl_;
responseStreaming_ = other.responseStreaming_;
options_ = other.options_.Clone();
+ syntax_ = other.syntax_;
}
public Method Clone() {
@@ -329,6 +378,15 @@ namespace Google.Protobuf.WellKnownTypes {
get { return options_; }
}
+ public const int SyntaxFieldNumber = 7;
+ private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2;
+ public global::Google.Protobuf.WellKnownTypes.Syntax Syntax {
+ get { return syntax_; }
+ set {
+ syntax_ = value;
+ }
+ }
+
public override bool Equals(object other) {
return Equals(other as Method);
}
@@ -346,6 +404,7 @@ namespace Google.Protobuf.WellKnownTypes {
if (ResponseTypeUrl != other.ResponseTypeUrl) return false;
if (ResponseStreaming != other.ResponseStreaming) return false;
if(!options_.Equals(other.options_)) return false;
+ if (Syntax != other.Syntax) return false;
return true;
}
@@ -357,6 +416,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();
return hash;
}
@@ -386,6 +446,10 @@ namespace Google.Protobuf.WellKnownTypes {
output.WriteBool(ResponseStreaming);
}
options_.WriteTo(output, _repeated_options_codec);
+ if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
+ output.WriteRawTag(56);
+ output.WriteEnum((int) Syntax);
+ }
}
public int CalculateSize() {
@@ -406,6 +470,9 @@ namespace Google.Protobuf.WellKnownTypes {
size += 1 + 1;
}
size += options_.CalculateSize(_repeated_options_codec);
+ if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
+ size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
+ }
return size;
}
@@ -429,6 +496,9 @@ namespace Google.Protobuf.WellKnownTypes {
ResponseStreaming = other.ResponseStreaming;
}
options_.Add(other.options_);
+ if (other.Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
+ Syntax = other.Syntax;
+ }
}
public void MergeFrom(pb::CodedInputStream input) {
@@ -462,6 +532,138 @@ namespace Google.Protobuf.WellKnownTypes {
options_.AddEntriesFrom(input, _repeated_options_codec);
break;
}
+ case 56: {
+ syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class Mixin : pb::IMessage<Mixin> {
+ private static readonly pb::MessageParser<Mixin> _parser = new pb::MessageParser<Mixin>(() => new Mixin());
+ public static pb::MessageParser<Mixin> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Google.Protobuf.WellKnownTypes.Proto.Api.Descriptor.MessageTypes[2]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public Mixin() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public Mixin(Mixin other) : this() {
+ name_ = other.name_;
+ root_ = other.root_;
+ }
+
+ public Mixin Clone() {
+ return new Mixin(this);
+ }
+
+ public const int NameFieldNumber = 1;
+ private string name_ = "";
+ public string Name {
+ get { return name_; }
+ set {
+ name_ = pb::Preconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ public const int RootFieldNumber = 2;
+ private string root_ = "";
+ public string Root {
+ get { return root_; }
+ set {
+ root_ = pb::Preconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as Mixin);
+ }
+
+ public bool Equals(Mixin other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (Name != other.Name) return false;
+ if (Root != other.Root) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (Name.Length != 0) hash ^= Name.GetHashCode();
+ if (Root.Length != 0) hash ^= Root.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.Default.Format(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (Name.Length != 0) {
+ output.WriteRawTag(10);
+ output.WriteString(Name);
+ }
+ if (Root.Length != 0) {
+ output.WriteRawTag(18);
+ output.WriteString(Root);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (Name.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+ }
+ if (Root.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Root);
+ }
+ return size;
+ }
+
+ public void MergeFrom(Mixin other) {
+ if (other == null) {
+ return;
+ }
+ if (other.Name.Length != 0) {
+ Name = other.Name;
+ }
+ if (other.Root.Length != 0) {
+ Root = other.Root;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10: {
+ Name = input.ReadString();
+ break;
+ }
+ case 18: {
+ Root = input.ReadString();
+ break;
+ }
}
}
}
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs
index aa34f2d8..fce1de0b 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs
@@ -23,10 +23,10 @@ namespace Google.Protobuf.WellKnownTypes {
static Duration() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "Ch5nb29nbGUvcHJvdG9idWYvZHVyYXRpb24ucHJvdG8SD2dvb2dsZS5wcm90",
- "b2J1ZiIqCghEdXJhdGlvbhIPCgdzZWNvbmRzGAEgASgDEg0KBW5hbm9zGAIg",
- "ASgFQlAKE2NvbS5nb29nbGUucHJvdG9idWZCDUR1cmF0aW9uUHJvdG9QAaAB",
- "AaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJv",
+ "Ch5nb29nbGUvcHJvdG9idWYvZHVyYXRpb24ucHJvdG8SD2dvb2dsZS5wcm90",
+ "b2J1ZiIqCghEdXJhdGlvbhIPCgdzZWNvbmRzGAEgASgDEg0KBW5hbm9zGAIg",
+ "ASgFQlAKE2NvbS5nb29nbGUucHJvdG9idWZCDUR1cmF0aW9uUHJvdG9QAaAB",
+ "AaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJv",
"dG8z"));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { },
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs
index 7d699c1d..2d87aaaa 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs
@@ -23,10 +23,10 @@ namespace Google.Protobuf.WellKnownTypes {
static Empty() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "Chtnb29nbGUvcHJvdG9idWYvZW1wdHkucHJvdG8SD2dvb2dsZS5wcm90b2J1",
- "ZiIHCgVFbXB0eUJKChNjb20uZ29vZ2xlLnByb3RvYnVmQgpFbXB0eVByb3Rv",
- "UAGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnBy",
- "b3RvMw=="));
+ "Chtnb29nbGUvcHJvdG9idWYvZW1wdHkucHJvdG8SD2dvb2dsZS5wcm90b2J1",
+ "ZiIHCgVFbXB0eUJNChNjb20uZ29vZ2xlLnByb3RvYnVmQgpFbXB0eVByb3Rv",
+ "UAGgAQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNi",
+ "BnByb3RvMw=="));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs
index 0dac4403..a73a6360 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs
@@ -23,10 +23,10 @@ namespace Google.Protobuf.WellKnownTypes {
static FieldMask() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "CiBnb29nbGUvcHJvdG9idWYvZmllbGRfbWFzay5wcm90bxIPZ29vZ2xlLnBy",
- "b3RvYnVmIhoKCUZpZWxkTWFzaxINCgVwYXRocxgBIAMoCUJOChNjb20uZ29v",
- "Z2xlLnByb3RvYnVmQg5GaWVsZE1hc2tQcm90b1ABogIDR1BCqgIeR29vZ2xl",
- "LlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZwcm90bzM="));
+ "CiBnb29nbGUvcHJvdG9idWYvZmllbGRfbWFzay5wcm90bxIPZ29vZ2xlLnBy",
+ "b3RvYnVmIhoKCUZpZWxkTWFzaxINCgVwYXRocxgBIAMoCUJRChNjb20uZ29v",
+ "Z2xlLnByb3RvYnVmQg5GaWVsZE1hc2tQcm90b1ABoAEBogIDR1BCqgIeR29v",
+ "Z2xlLlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZwcm90bzM="));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs
index 8347999d..d80c50f3 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs
@@ -23,11 +23,11 @@ namespace Google.Protobuf.WellKnownTypes {
static SourceContext() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "CiRnb29nbGUvcHJvdG9idWYvc291cmNlX2NvbnRleHQucHJvdG8SD2dvb2ds",
- "ZS5wcm90b2J1ZiIiCg1Tb3VyY2VDb250ZXh0EhEKCWZpbGVfbmFtZRgBIAEo",
- "CUJSChNjb20uZ29vZ2xlLnByb3RvYnVmQhJTb3VyY2VDb250ZXh0UHJvdG9Q",
- "AaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJv",
- "dG8z"));
+ "CiRnb29nbGUvcHJvdG9idWYvc291cmNlX2NvbnRleHQucHJvdG8SD2dvb2ds",
+ "ZS5wcm90b2J1ZiIiCg1Tb3VyY2VDb250ZXh0EhEKCWZpbGVfbmFtZRgBIAEo",
+ "CUJVChNjb20uZ29vZ2xlLnByb3RvYnVmQhJTb3VyY2VDb250ZXh0UHJvdG9Q",
+ "AaABAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IG",
+ "cHJvdG8z"));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
index 1e8a8236..cab771c0 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
@@ -23,19 +23,19 @@ namespace Google.Protobuf.WellKnownTypes {
static Struct() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "Chxnb29nbGUvcHJvdG9idWYvc3RydWN0LnByb3RvEg9nb29nbGUucHJvdG9i",
- "dWYihAEKBlN0cnVjdBIzCgZmaWVsZHMYASADKAsyIy5nb29nbGUucHJvdG9i",
- "dWYuU3RydWN0LkZpZWxkc0VudHJ5GkUKC0ZpZWxkc0VudHJ5EgsKA2tleRgB",
- "IAEoCRIlCgV2YWx1ZRgCIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5WYWx1ZToC",
- "OAEi6gEKBVZhbHVlEjAKCm51bGxfdmFsdWUYASABKA4yGi5nb29nbGUucHJv",
- "dG9idWYuTnVsbFZhbHVlSAASFgoMbnVtYmVyX3ZhbHVlGAIgASgBSAASFgoM",
- "c3RyaW5nX3ZhbHVlGAMgASgJSAASFAoKYm9vbF92YWx1ZRgEIAEoCEgAEi8K",
- "DHN0cnVjdF92YWx1ZRgFIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RI",
- "ABIwCgpsaXN0X3ZhbHVlGAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLkxpc3RW",
- "YWx1ZUgAQgYKBGtpbmQiMwoJTGlzdFZhbHVlEiYKBnZhbHVlcxgBIAMoCzIW",
- "Lmdvb2dsZS5wcm90b2J1Zi5WYWx1ZSobCglOdWxsVmFsdWUSDgoKTlVMTF9W",
- "QUxVRRAAQk4KE2NvbS5nb29nbGUucHJvdG9idWZCC1N0cnVjdFByb3RvUAGg",
- "AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnBy",
+ "Chxnb29nbGUvcHJvdG9idWYvc3RydWN0LnByb3RvEg9nb29nbGUucHJvdG9i",
+ "dWYihAEKBlN0cnVjdBIzCgZmaWVsZHMYASADKAsyIy5nb29nbGUucHJvdG9i",
+ "dWYuU3RydWN0LkZpZWxkc0VudHJ5GkUKC0ZpZWxkc0VudHJ5EgsKA2tleRgB",
+ "IAEoCRIlCgV2YWx1ZRgCIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5WYWx1ZToC",
+ "OAEi6gEKBVZhbHVlEjAKCm51bGxfdmFsdWUYASABKA4yGi5nb29nbGUucHJv",
+ "dG9idWYuTnVsbFZhbHVlSAASFgoMbnVtYmVyX3ZhbHVlGAIgASgBSAASFgoM",
+ "c3RyaW5nX3ZhbHVlGAMgASgJSAASFAoKYm9vbF92YWx1ZRgEIAEoCEgAEi8K",
+ "DHN0cnVjdF92YWx1ZRgFIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RI",
+ "ABIwCgpsaXN0X3ZhbHVlGAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLkxpc3RW",
+ "YWx1ZUgAQgYKBGtpbmQiMwoJTGlzdFZhbHVlEiYKBnZhbHVlcxgBIAMoCzIW",
+ "Lmdvb2dsZS5wcm90b2J1Zi5WYWx1ZSobCglOdWxsVmFsdWUSDgoKTlVMTF9W",
+ "QUxVRRAAQk4KE2NvbS5nb29nbGUucHJvdG9idWZCC1N0cnVjdFByb3RvUAGg",
+ "AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnBy",
"b3RvMw=="));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { },
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs
index d7c0954f..5c652dc2 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs
@@ -23,10 +23,10 @@ namespace Google.Protobuf.WellKnownTypes {
static Timestamp() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "Ch9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1wLnByb3RvEg9nb29nbGUucHJv",
- "dG9idWYiKwoJVGltZXN0YW1wEg8KB3NlY29uZHMYASABKAMSDQoFbmFub3MY",
- "AiABKAVCUQoTY29tLmdvb2dsZS5wcm90b2J1ZkIOVGltZXN0YW1wUHJvdG9Q",
- "AaABAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IG",
+ "Ch9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1wLnByb3RvEg9nb29nbGUucHJv",
+ "dG9idWYiKwoJVGltZXN0YW1wEg8KB3NlY29uZHMYASABKAMSDQoFbmFub3MY",
+ "AiABKAVCUQoTY29tLmdvb2dsZS5wcm90b2J1ZkIOVGltZXN0YW1wUHJvdG9Q",
+ "AaABAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IG",
"cHJvdG8z"));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { },
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
index ff2ecc57..eb676945 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
@@ -23,43 +23,46 @@ namespace Google.Protobuf.WellKnownTypes {
static Type() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "Chpnb29nbGUvcHJvdG9idWYvdHlwZS5wcm90bxIPZ29vZ2xlLnByb3RvYnVm",
- "Ghlnb29nbGUvcHJvdG9idWYvYW55LnByb3RvGiRnb29nbGUvcHJvdG9idWYv",
- "c291cmNlX2NvbnRleHQucHJvdG8irgEKBFR5cGUSDAoEbmFtZRgBIAEoCRIm",
- "CgZmaWVsZHMYAiADKAsyFi5nb29nbGUucHJvdG9idWYuRmllbGQSDgoGb25l",
- "b2ZzGAMgAygJEigKB29wdGlvbnMYBCADKAsyFy5nb29nbGUucHJvdG9idWYu",
- "T3B0aW9uEjYKDnNvdXJjZV9jb250ZXh0GAUgASgLMh4uZ29vZ2xlLnByb3Rv",
- "YnVmLlNvdXJjZUNvbnRleHQimwUKBUZpZWxkEikKBGtpbmQYASABKA4yGy5n",
- "b29nbGUucHJvdG9idWYuRmllbGQuS2luZBI3CgtjYXJkaW5hbGl0eRgCIAEo",
- "DjIiLmdvb2dsZS5wcm90b2J1Zi5GaWVsZC5DYXJkaW5hbGl0eRIOCgZudW1i",
- "ZXIYAyABKAUSDAoEbmFtZRgEIAEoCRIQCgh0eXBlX3VybBgGIAEoCRITCgtv",
- "bmVvZl9pbmRleBgHIAEoBRIOCgZwYWNrZWQYCCABKAgSKAoHb3B0aW9ucxgJ",
- "IAMoCzIXLmdvb2dsZS5wcm90b2J1Zi5PcHRpb24iuAIKBEtpbmQSEAoMVFlQ",
- "RV9VTktOT1dOEAASDwoLVFlQRV9ET1VCTEUQARIOCgpUWVBFX0ZMT0FUEAIS",
- "DgoKVFlQRV9JTlQ2NBADEg8KC1RZUEVfVUlOVDY0EAQSDgoKVFlQRV9JTlQz",
- "MhAFEhAKDFRZUEVfRklYRUQ2NBAGEhAKDFRZUEVfRklYRUQzMhAHEg0KCVRZ",
- "UEVfQk9PTBAIEg8KC1RZUEVfU1RSSU5HEAkSEAoMVFlQRV9NRVNTQUdFEAsS",
- "DgoKVFlQRV9CWVRFUxAMEg8KC1RZUEVfVUlOVDMyEA0SDQoJVFlQRV9FTlVN",
- "EA4SEQoNVFlQRV9TRklYRUQzMhAPEhEKDVRZUEVfU0ZJWEVENjQQEBIPCgtU",
- "WVBFX1NJTlQzMhAREg8KC1RZUEVfU0lOVDY0EBIidAoLQ2FyZGluYWxpdHkS",
- "FwoTQ0FSRElOQUxJVFlfVU5LTk9XThAAEhgKFENBUkRJTkFMSVRZX09QVElP",
- "TkFMEAESGAoUQ0FSRElOQUxJVFlfUkVRVUlSRUQQAhIYChRDQVJESU5BTElU",
- "WV9SRVBFQVRFRBADIqUBCgRFbnVtEgwKBG5hbWUYASABKAkSLQoJZW51bXZh",
- "bHVlGAIgAygLMhouZ29vZ2xlLnByb3RvYnVmLkVudW1WYWx1ZRIoCgdvcHRp",
- "b25zGAMgAygLMhcuZ29vZ2xlLnByb3RvYnVmLk9wdGlvbhI2Cg5zb3VyY2Vf",
- "Y29udGV4dBgEIAEoCzIeLmdvb2dsZS5wcm90b2J1Zi5Tb3VyY2VDb250ZXh0",
- "IlMKCUVudW1WYWx1ZRIMCgRuYW1lGAEgASgJEg4KBm51bWJlchgCIAEoBRIo",
- "CgdvcHRpb25zGAMgAygLMhcuZ29vZ2xlLnByb3RvYnVmLk9wdGlvbiI7CgZP",
- "cHRpb24SDAoEbmFtZRgBIAEoCRIjCgV2YWx1ZRgCIAEoCzIULmdvb2dsZS5w",
- "cm90b2J1Zi5BbnlCSQoTY29tLmdvb2dsZS5wcm90b2J1ZkIJVHlwZVByb3Rv",
- "UAGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnBy",
- "b3RvMw=="));
+ "Chpnb29nbGUvcHJvdG9idWYvdHlwZS5wcm90bxIPZ29vZ2xlLnByb3RvYnVm",
+ "Ghlnb29nbGUvcHJvdG9idWYvYW55LnByb3RvGiRnb29nbGUvcHJvdG9idWYv",
+ "c291cmNlX2NvbnRleHQucHJvdG8i1wEKBFR5cGUSDAoEbmFtZRgBIAEoCRIm",
+ "CgZmaWVsZHMYAiADKAsyFi5nb29nbGUucHJvdG9idWYuRmllbGQSDgoGb25l",
+ "b2ZzGAMgAygJEigKB29wdGlvbnMYBCADKAsyFy5nb29nbGUucHJvdG9idWYu",
+ "T3B0aW9uEjYKDnNvdXJjZV9jb250ZXh0GAUgASgLMh4uZ29vZ2xlLnByb3Rv",
+ "YnVmLlNvdXJjZUNvbnRleHQSJwoGc3ludGF4GAYgASgOMhcuZ29vZ2xlLnBy",
+ "b3RvYnVmLlN5bnRheCK+BQoFRmllbGQSKQoEa2luZBgBIAEoDjIbLmdvb2ds",
+ "ZS5wcm90b2J1Zi5GaWVsZC5LaW5kEjcKC2NhcmRpbmFsaXR5GAIgASgOMiIu",
+ "Z29vZ2xlLnByb3RvYnVmLkZpZWxkLkNhcmRpbmFsaXR5Eg4KBm51bWJlchgD",
+ "IAEoBRIMCgRuYW1lGAQgASgJEhAKCHR5cGVfdXJsGAYgASgJEhMKC29uZW9m",
+ "X2luZGV4GAcgASgFEg4KBnBhY2tlZBgIIAEoCBIoCgdvcHRpb25zGAkgAygL",
+ "MhcuZ29vZ2xlLnByb3RvYnVmLk9wdGlvbhIRCglqc29uX25hbWUYCiABKAki",
+ "yAIKBEtpbmQSEAoMVFlQRV9VTktOT1dOEAASDwoLVFlQRV9ET1VCTEUQARIO",
+ "CgpUWVBFX0ZMT0FUEAISDgoKVFlQRV9JTlQ2NBADEg8KC1RZUEVfVUlOVDY0",
+ "EAQSDgoKVFlQRV9JTlQzMhAFEhAKDFRZUEVfRklYRUQ2NBAGEhAKDFRZUEVf",
+ "RklYRUQzMhAHEg0KCVRZUEVfQk9PTBAIEg8KC1RZUEVfU1RSSU5HEAkSDgoK",
+ "VFlQRV9HUk9VUBAKEhAKDFRZUEVfTUVTU0FHRRALEg4KClRZUEVfQllURVMQ",
+ "DBIPCgtUWVBFX1VJTlQzMhANEg0KCVRZUEVfRU5VTRAOEhEKDVRZUEVfU0ZJ",
+ "WEVEMzIQDxIRCg1UWVBFX1NGSVhFRDY0EBASDwoLVFlQRV9TSU5UMzIQERIP",
+ "CgtUWVBFX1NJTlQ2NBASInQKC0NhcmRpbmFsaXR5EhcKE0NBUkRJTkFMSVRZ",
+ "X1VOS05PV04QABIYChRDQVJESU5BTElUWV9PUFRJT05BTBABEhgKFENBUkRJ",
+ "TkFMSVRZX1JFUVVJUkVEEAISGAoUQ0FSRElOQUxJVFlfUkVQRUFURUQQAyLO",
+ "AQoERW51bRIMCgRuYW1lGAEgASgJEi0KCWVudW12YWx1ZRgCIAMoCzIaLmdv",
+ "b2dsZS5wcm90b2J1Zi5FbnVtVmFsdWUSKAoHb3B0aW9ucxgDIAMoCzIXLmdv",
+ "b2dsZS5wcm90b2J1Zi5PcHRpb24SNgoOc291cmNlX2NvbnRleHQYBCABKAsy",
+ "Hi5nb29nbGUucHJvdG9idWYuU291cmNlQ29udGV4dBInCgZzeW50YXgYBSAB",
+ "KA4yFy5nb29nbGUucHJvdG9idWYuU3ludGF4IlMKCUVudW1WYWx1ZRIMCgRu",
+ "YW1lGAEgASgJEg4KBm51bWJlchgCIAEoBRIoCgdvcHRpb25zGAMgAygLMhcu",
+ "Z29vZ2xlLnByb3RvYnVmLk9wdGlvbiI7CgZPcHRpb24SDAoEbmFtZRgBIAEo",
+ "CRIjCgV2YWx1ZRgCIAEoCzIULmdvb2dsZS5wcm90b2J1Zi5BbnkqLgoGU3lu",
+ "dGF4EhEKDVNZTlRBWF9QUk9UTzIQABIRCg1TWU5UQVhfUFJPVE8zEAFCTAoT",
+ "Y29tLmdvb2dsZS5wcm90b2J1ZkIJVHlwZVByb3RvUAGgAQGiAgNHUEKqAh5H",
+ "b29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw=="));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.Proto.Any.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.SourceContext.Descriptor, },
- new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
- new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Type), new[]{ "Name", "Fields", "Oneofs", "Options", "SourceContext" }, null, null, null),
- new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Field), new[]{ "Kind", "Cardinality", "Number", "Name", "TypeUrl", "OneofIndex", "Packed", "Options" }, null, new[]{ typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Kind), typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) }, null),
- new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Enum), new[]{ "Name", "Enumvalue", "Options", "SourceContext" }, null, null, null),
+ new pbr::GeneratedCodeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.Syntax), }, new pbr::GeneratedCodeInfo[] {
+ new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Type), new[]{ "Name", "Fields", "Oneofs", "Options", "SourceContext", "Syntax" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Field), new[]{ "Kind", "Cardinality", "Number", "Name", "TypeUrl", "OneofIndex", "Packed", "Options", "JsonName" }, null, new[]{ typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Kind), typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) }, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Enum), new[]{ "Name", "Enumvalue", "Options", "SourceContext", "Syntax" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.EnumValue), new[]{ "Name", "Number", "Options" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Option), new[]{ "Name", "Value" }, null, null, null)
}));
@@ -68,6 +71,14 @@ namespace Google.Protobuf.WellKnownTypes {
}
}
+ #region Enums
+ public enum Syntax {
+ SYNTAX_PROTO2 = 0,
+ SYNTAX_PROTO3 = 1,
+ }
+
+ #endregion
+
#region Messages
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class Type : pb::IMessage<Type> {
@@ -94,6 +105,7 @@ namespace Google.Protobuf.WellKnownTypes {
oneofs_ = other.oneofs_.Clone();
options_ = other.options_.Clone();
SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null;
+ syntax_ = other.syntax_;
}
public Type Clone() {
@@ -142,6 +154,15 @@ namespace Google.Protobuf.WellKnownTypes {
}
}
+ public const int SyntaxFieldNumber = 6;
+ private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2;
+ public global::Google.Protobuf.WellKnownTypes.Syntax Syntax {
+ get { return syntax_; }
+ set {
+ syntax_ = value;
+ }
+ }
+
public override bool Equals(object other) {
return Equals(other as Type);
}
@@ -158,6 +179,7 @@ namespace Google.Protobuf.WellKnownTypes {
if(!oneofs_.Equals(other.oneofs_)) return false;
if(!options_.Equals(other.options_)) return false;
if (!object.Equals(SourceContext, other.SourceContext)) return false;
+ if (Syntax != other.Syntax) return false;
return true;
}
@@ -168,6 +190,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();
return hash;
}
@@ -187,6 +210,10 @@ namespace Google.Protobuf.WellKnownTypes {
output.WriteRawTag(42);
output.WriteMessage(SourceContext);
}
+ if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
+ output.WriteRawTag(48);
+ output.WriteEnum((int) Syntax);
+ }
}
public int CalculateSize() {
@@ -200,6 +227,9 @@ namespace Google.Protobuf.WellKnownTypes {
if (sourceContext_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContext);
}
+ if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
+ size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
+ }
return size;
}
@@ -219,6 +249,9 @@ namespace Google.Protobuf.WellKnownTypes {
}
SourceContext.MergeFrom(other.SourceContext);
}
+ if (other.Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
+ Syntax = other.Syntax;
+ }
}
public void MergeFrom(pb::CodedInputStream input) {
@@ -251,6 +284,10 @@ namespace Google.Protobuf.WellKnownTypes {
input.ReadMessage(sourceContext_);
break;
}
+ case 48: {
+ syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
+ break;
+ }
}
}
}
@@ -285,6 +322,7 @@ namespace Google.Protobuf.WellKnownTypes {
oneofIndex_ = other.oneofIndex_;
packed_ = other.packed_;
options_ = other.options_.Clone();
+ jsonName_ = other.jsonName_;
}
public Field Clone() {
@@ -362,6 +400,15 @@ namespace Google.Protobuf.WellKnownTypes {
get { return options_; }
}
+ public const int JsonNameFieldNumber = 10;
+ private string jsonName_ = "";
+ public string JsonName {
+ get { return jsonName_; }
+ set {
+ jsonName_ = pb::Preconditions.CheckNotNull(value, "value");
+ }
+ }
+
public override bool Equals(object other) {
return Equals(other as Field);
}
@@ -381,6 +428,7 @@ namespace Google.Protobuf.WellKnownTypes {
if (OneofIndex != other.OneofIndex) return false;
if (Packed != other.Packed) return false;
if(!options_.Equals(other.options_)) return false;
+ if (JsonName != other.JsonName) return false;
return true;
}
@@ -394,6 +442,7 @@ namespace Google.Protobuf.WellKnownTypes {
if (OneofIndex != 0) hash ^= OneofIndex.GetHashCode();
if (Packed != false) hash ^= Packed.GetHashCode();
hash ^= options_.GetHashCode();
+ if (JsonName.Length != 0) hash ^= JsonName.GetHashCode();
return hash;
}
@@ -431,6 +480,10 @@ namespace Google.Protobuf.WellKnownTypes {
output.WriteBool(Packed);
}
options_.WriteTo(output, _repeated_options_codec);
+ if (JsonName.Length != 0) {
+ output.WriteRawTag(82);
+ output.WriteString(JsonName);
+ }
}
public int CalculateSize() {
@@ -457,6 +510,9 @@ namespace Google.Protobuf.WellKnownTypes {
size += 1 + 1;
}
size += options_.CalculateSize(_repeated_options_codec);
+ if (JsonName.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonName);
+ }
return size;
}
@@ -486,6 +542,9 @@ namespace Google.Protobuf.WellKnownTypes {
Packed = other.Packed;
}
options_.Add(other.options_);
+ if (other.JsonName.Length != 0) {
+ JsonName = other.JsonName;
+ }
}
public void MergeFrom(pb::CodedInputStream input) {
@@ -527,6 +586,10 @@ namespace Google.Protobuf.WellKnownTypes {
options_.AddEntriesFrom(input, _repeated_options_codec);
break;
}
+ case 82: {
+ JsonName = input.ReadString();
+ break;
+ }
}
}
}
@@ -545,6 +608,7 @@ namespace Google.Protobuf.WellKnownTypes {
TYPE_FIXED32 = 7,
TYPE_BOOL = 8,
TYPE_STRING = 9,
+ TYPE_GROUP = 10,
TYPE_MESSAGE = 11,
TYPE_BYTES = 12,
TYPE_UINT32 = 13,
@@ -591,6 +655,7 @@ namespace Google.Protobuf.WellKnownTypes {
enumvalue_ = other.enumvalue_.Clone();
options_ = other.options_.Clone();
SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null;
+ syntax_ = other.syntax_;
}
public Enum Clone() {
@@ -631,6 +696,15 @@ namespace Google.Protobuf.WellKnownTypes {
}
}
+ public const int SyntaxFieldNumber = 5;
+ private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2;
+ public global::Google.Protobuf.WellKnownTypes.Syntax Syntax {
+ get { return syntax_; }
+ set {
+ syntax_ = value;
+ }
+ }
+
public override bool Equals(object other) {
return Equals(other as Enum);
}
@@ -646,6 +720,7 @@ namespace Google.Protobuf.WellKnownTypes {
if(!enumvalue_.Equals(other.enumvalue_)) return false;
if(!options_.Equals(other.options_)) return false;
if (!object.Equals(SourceContext, other.SourceContext)) return false;
+ if (Syntax != other.Syntax) return false;
return true;
}
@@ -655,6 +730,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();
return hash;
}
@@ -673,6 +749,10 @@ namespace Google.Protobuf.WellKnownTypes {
output.WriteRawTag(34);
output.WriteMessage(SourceContext);
}
+ if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
+ output.WriteRawTag(40);
+ output.WriteEnum((int) Syntax);
+ }
}
public int CalculateSize() {
@@ -685,6 +765,9 @@ namespace Google.Protobuf.WellKnownTypes {
if (sourceContext_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContext);
}
+ if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
+ size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
+ }
return size;
}
@@ -703,6 +786,9 @@ namespace Google.Protobuf.WellKnownTypes {
}
SourceContext.MergeFrom(other.SourceContext);
}
+ if (other.Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.SYNTAX_PROTO2) {
+ Syntax = other.Syntax;
+ }
}
public void MergeFrom(pb::CodedInputStream input) {
@@ -731,6 +817,10 @@ namespace Google.Protobuf.WellKnownTypes {
input.ReadMessage(sourceContext_);
break;
}
+ case 40: {
+ syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
+ break;
+ }
}
}
}
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs
index 9ecaf47c..7e63d805 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs
@@ -21,15 +21,15 @@ namespace Google.Protobuf.WellKnownTypes {
static Wrappers() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "Ch5nb29nbGUvcHJvdG9idWYvd3JhcHBlcnMucHJvdG8SD2dvb2dsZS5wcm90",
- "b2J1ZiIcCgtEb3VibGVWYWx1ZRINCgV2YWx1ZRgBIAEoASIbCgpGbG9hdFZh",
- "bHVlEg0KBXZhbHVlGAEgASgCIhsKCkludDY0VmFsdWUSDQoFdmFsdWUYASAB",
- "KAMiHAoLVUludDY0VmFsdWUSDQoFdmFsdWUYASABKAQiGwoKSW50MzJWYWx1",
- "ZRINCgV2YWx1ZRgBIAEoBSIcCgtVSW50MzJWYWx1ZRINCgV2YWx1ZRgBIAEo",
- "DSIaCglCb29sVmFsdWUSDQoFdmFsdWUYASABKAgiHAoLU3RyaW5nVmFsdWUS",
- "DQoFdmFsdWUYASABKAkiGwoKQnl0ZXNWYWx1ZRINCgV2YWx1ZRgBIAEoDEJN",
- "ChNjb20uZ29vZ2xlLnByb3RvYnVmQg1XcmFwcGVyc1Byb3RvUAGiAgNHUEKq",
- "Ah5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw=="));
+ "Ch5nb29nbGUvcHJvdG9idWYvd3JhcHBlcnMucHJvdG8SD2dvb2dsZS5wcm90",
+ "b2J1ZiIcCgtEb3VibGVWYWx1ZRINCgV2YWx1ZRgBIAEoASIbCgpGbG9hdFZh",
+ "bHVlEg0KBXZhbHVlGAEgASgCIhsKCkludDY0VmFsdWUSDQoFdmFsdWUYASAB",
+ "KAMiHAoLVUludDY0VmFsdWUSDQoFdmFsdWUYASABKAQiGwoKSW50MzJWYWx1",
+ "ZRINCgV2YWx1ZRgBIAEoBSIcCgtVSW50MzJWYWx1ZRINCgV2YWx1ZRgBIAEo",
+ "DSIaCglCb29sVmFsdWUSDQoFdmFsdWUYASABKAgiHAoLU3RyaW5nVmFsdWUS",
+ "DQoFdmFsdWUYASABKAkiGwoKQnl0ZXNWYWx1ZRINCgV2YWx1ZRgBIAEoDEJQ",
+ "ChNjb20uZ29vZ2xlLnByb3RvYnVmQg1XcmFwcGVyc1Byb3RvUAGgAQGiAgNH",
+ "UEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw=="));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh
index b6e6e07b..cd906896 100755
--- a/generate_descriptor_proto.sh
+++ b/generate_descriptor_proto.sh
@@ -92,3 +92,8 @@ do
PROCESS_ROUND=$((PROCESS_ROUND + 1))
done
cd ..
+
+if test -x objectivec/generate_descriptors_proto.sh; then
+ echo "Generating messages for objc."
+ objectivec/generate_descriptors_proto.sh $@
+fi
diff --git a/java/pom.xml b/java/pom.xml
index 6877ac27..8b81b645 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -10,7 +10,7 @@
</parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
- <version>3.0.0-alpha-4-pre</version>
+ <version>3.0.0-beta-1</version>
<packaging>bundle</packaging>
<name>Protocol Buffer Java API</name>
<description>
@@ -114,6 +114,7 @@
<arg value="../src/google/protobuf/unittest_import.proto" />
<arg value="../src/google/protobuf/unittest_import_public.proto" />
<arg value="../src/google/protobuf/unittest_mset.proto" />
+ <arg value="../src/google/protobuf/unittest_mset_wire_format.proto" />
<arg value="src/test/java/com/google/protobuf/lazy_fields_lite.proto" />
<arg value="src/test/java/com/google/protobuf/lite_equals_and_hash.proto" />
<arg
@@ -141,6 +142,7 @@
<arg value="../src/google/protobuf/unittest_enormous_descriptor.proto" />
<arg value="../src/google/protobuf/unittest_no_generic_services.proto" />
<arg value="../src/google/protobuf/unittest_well_known_types.proto" />
+ <arg value="src/test/java/com/google/protobuf/any_test.proto" />
<arg value="src/test/java/com/google/protobuf/field_presence_test.proto" />
<arg value="src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto" />
<arg value="src/test/java/com/google/protobuf/map_for_proto2_test.proto" />
@@ -164,7 +166,7 @@
<instructions>
<Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
<Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName>
- <Export-Package>com.google.protobuf;version=3.0.0-alpha-3</Export-Package>
+ <Export-Package>com.google.protobuf;version=3.0.0-beta-1</Export-Package>
</instructions>
</configuration>
</plugin>
diff --git a/java/src/main/java/com/google/protobuf/ByteString.java b/java/src/main/java/com/google/protobuf/ByteString.java
index 1d5d4e8a..b092bc36 100644
--- a/java/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/src/main/java/com/google/protobuf/ByteString.java
@@ -94,7 +94,7 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
*
* @param index index of byte
* @return the value
- * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
+ * @throws ArrayIndexOutOfBoundsException {@code index < 0 or index >= size}
*/
public abstract byte byteAt(int index);
@@ -294,10 +294,10 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
* <b>Performance notes:</b> The returned {@code ByteString} is an
* immutable tree of byte arrays ("chunks") of the stream data. The
* first chunk is small, with subsequent chunks each being double
- * the size, up to 8K. If the caller knows the precise length of
- * the stream and wishes to avoid all unnecessary copies and
- * allocations, consider using the two-argument version of this
- * method, below.
+ * the size, up to 8K.
+ *
+ * <p>Each byte read from the input stream will be copied twice to ensure
+ * that the resulting ByteString is truly immutable.
*
* @param streamToDrain The source stream, which is read completely
* but not closed.
@@ -320,12 +320,10 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
*
* <b>Performance notes:</b> The returned {@code ByteString} is an
* immutable tree of byte arrays ("chunks") of the stream data. The
- * chunkSize parameter sets the size of these byte arrays. In
- * particular, if the chunkSize is precisely the same as the length
- * of the stream, unnecessary allocations and copies will be
- * avoided. Otherwise, the chunks will be of the given size, except
- * for the last chunk, which will be resized (via a reallocation and
- * copy) to contain the remainder of the stream.
+ * chunkSize parameter sets the size of these byte arrays.
+ *
+ * <p>Each byte read from the input stream will be copied twice to ensure
+ * that the resulting ByteString is truly immutable.
*
* @param streamToDrain The source stream, which is read completely
* but not closed.
@@ -386,6 +384,7 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
if (bytesRead == 0) {
return null;
} else {
+ // Always make a copy since InputStream could steal a reference to buf.
return ByteString.copyFrom(buf, 0, bytesRead);
}
}
@@ -680,8 +679,8 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
* sequences, but (as of 2011) still accepts 3-byte surrogate
* character byte sequences.
*
- * <p>See the Unicode Standard,</br>
- * Table 3-6. <em>UTF-8 Bit Distribution</em>,</br>
+ * <p>See the Unicode Standard,<br>
+ * Table 3-6. <em>UTF-8 Bit Distribution</em>,<br>
* Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
*
* @return whether the bytes in this {@code ByteString} are a
@@ -736,7 +735,8 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
* returns the number of bytes remaining in the stream. The methods
* {@link InputStream#read(byte[])}, {@link InputStream#read(byte[],int,int)}
* and {@link InputStream#skip(long)} will read/skip as many bytes as are
- * available.
+ * available. The method {@link InputStream#markSupported()} returns
+ * {@code true}.
* <p>
* The methods in the returned {@link InputStream} might <b>not</b> be
* thread safe.
diff --git a/java/src/main/java/com/google/protobuf/CodedOutputStream.java b/java/src/main/java/com/google/protobuf/CodedOutputStream.java
index 954fde08..291bd20a 100644
--- a/java/src/main/java/com/google/protobuf/CodedOutputStream.java
+++ b/java/src/main/java/com/google/protobuf/CodedOutputStream.java
@@ -30,9 +30,13 @@
package com.google.protobuf;
+import com.google.protobuf.Utf8.UnpairedSurrogateException;
+
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
/**
* Encodes and writes protocol message fields.
@@ -49,6 +53,10 @@ import java.nio.ByteBuffer;
* @author kneton@google.com Kenton Varda
*/
public final class CodedOutputStream {
+
+ private static final Logger logger = Logger.getLogger(CodedOutputStream.class.getName());
+
+ // TODO(dweis): Consider migrating to a ByteBuffer.
private final byte[] buffer;
private final int limit;
private int position;
@@ -415,15 +423,87 @@ public final class CodedOutputStream {
}
/** 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);
+ }
+ }
+
+ /** 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 {@code group} field to the stream. */
public void writeGroupNoTag(final MessageLite value) throws IOException {
value.writeTo(this);
@@ -826,9 +906,16 @@ public final class CodedOutputStream {
* {@code string} field.
*/
public static int computeStringSizeNoTag(final String value) {
- final byte[] bytes = value.getBytes(Internal.UTF_8);
- return computeRawVarint32Size(bytes.length) +
- bytes.length;
+ int length;
+ try {
+ length = Utf8.encodedLength(value);
+ } catch (UnpairedSurrogateException e) {
+ // TODO(dweis): Consider using nio Charset methods instead.
+ final byte[] bytes = value.getBytes(Internal.UTF_8);
+ length = bytes.length;
+ }
+
+ return computeRawVarint32Size(length) + length;
}
/**
@@ -1007,9 +1094,15 @@ public final class CodedOutputStream {
public static class OutOfSpaceException extends IOException {
private static final long serialVersionUID = -6947486886997889499L;
+ private static final String MESSAGE =
+ "CodedOutputStream was writing to a flat byte array and ran out of space.";
+
OutOfSpaceException() {
- super("CodedOutputStream was writing to a flat byte array and ran " +
- "out of space.");
+ super(MESSAGE);
+ }
+
+ OutOfSpaceException(Throwable cause) {
+ super(MESSAGE, cause);
}
}
diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java
index 3658410c..7cfc47f7 100644
--- a/java/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/src/main/java/com/google/protobuf/Descriptors.java
@@ -31,6 +31,7 @@
package com.google.protobuf;
import com.google.protobuf.DescriptorProtos.*;
+import com.google.protobuf.Descriptors.FileDescriptor.Syntax;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -912,7 +913,17 @@ public final class Descriptors {
/** For internal use only. */
public boolean needsUtf8Check() {
- return (type == Type.STRING) && (getFile().getOptions().getJavaStringCheckUtf8());
+ if (type != Type.STRING) {
+ return false;
+ }
+ if (getContainingType().getOptions().getMapEntry()) {
+ // Always enforce strict UTF-8 checking for map fields.
+ return true;
+ }
+ if (getFile().getSyntax() == Syntax.PROTO3) {
+ return true;
+ }
+ return getFile().getOptions().getJavaStringCheckUtf8();
}
public boolean isMapField() {
@@ -1118,9 +1129,9 @@ public final class Descriptors {
static {
// Refuse to init if someone added a new declared type.
if (Type.values().length != FieldDescriptorProto.Type.values().length) {
- throw new RuntimeException(
- "descriptor.proto has a new declared type but Desrciptors.java " +
- "wasn't updated.");
+ throw new RuntimeException(""
+ + "descriptor.proto has a new declared type but Descriptors.java "
+ + "wasn't updated.");
}
}
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
index 9457d999..d84fa75c 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -121,22 +121,44 @@ public abstract class GeneratedMessage extends AbstractMessage
final TreeMap<FieldDescriptor, Object> result =
new TreeMap<FieldDescriptor, Object>();
final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
- for (final FieldDescriptor field : descriptor.getFields()) {
- if (field.isRepeated()) {
- final List<?> value = (List<?>) getField(field);
- if (!value.isEmpty()) {
- result.put(field, value);
+ final List<FieldDescriptor> fields = descriptor.getFields();
+
+ for (int i = 0; i < fields.size(); i++) {
+ FieldDescriptor field = fields.get(i);
+ final OneofDescriptor oneofDescriptor = field.getContainingOneof();
+
+ /*
+ * If the field is part of a Oneof, then at maximum one field in the Oneof is set
+ * and it is not repeated. There is no need to iterate through the others.
+ */
+ if (oneofDescriptor != null) {
+ // Skip other fields in the Oneof we know are not set
+ i += oneofDescriptor.getFieldCount() - 1;
+ if (!hasOneof(oneofDescriptor)) {
+ // If no field is set in the Oneof, skip all the fields in the Oneof
+ continue;
}
+ // Get the pointer to the only field which is set in the Oneof
+ field = getOneofFieldDescriptor(oneofDescriptor);
} else {
- if (hasField(field)) {
- if (getBytesForString
- && field.getJavaType() == FieldDescriptor.JavaType.STRING) {
- result.put(field, getFieldRaw(field));
- } else {
- result.put(field, getField(field));
+ // If we are not in a Oneof, we need to check if the field is set and if it is repeated
+ if (field.isRepeated()) {
+ final List<?> value = (List<?>) getField(field);
+ if (!value.isEmpty()) {
+ result.put(field, value);
}
+ continue;
+ }
+ if (!hasField(field)) {
+ continue;
}
}
+ // Add the field to the map
+ if (getBytesForString && field.getJavaType() == FieldDescriptor.JavaType.STRING) {
+ result.put(field, getFieldRaw(field));
+ } else {
+ result.put(field, getField(field));
+ }
}
return result;
}
@@ -398,17 +420,40 @@ public abstract class GeneratedMessage extends AbstractMessage
final TreeMap<FieldDescriptor, Object> result =
new TreeMap<FieldDescriptor, Object>();
final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
- for (final FieldDescriptor field : descriptor.getFields()) {
- if (field.isRepeated()) {
- final List value = (List) getField(field);
- if (!value.isEmpty()) {
- result.put(field, value);
+ final List<FieldDescriptor> fields = descriptor.getFields();
+
+ for (int i = 0; i < fields.size(); i++) {
+ FieldDescriptor field = fields.get(i);
+ final OneofDescriptor oneofDescriptor = field.getContainingOneof();
+
+ /*
+ * If the field is part of a Oneof, then at maximum one field in the Oneof is set
+ * and it is not repeated. There is no need to iterate through the others.
+ */
+ if (oneofDescriptor != null) {
+ // Skip other fields in the Oneof we know are not set
+ i += oneofDescriptor.getFieldCount() - 1;
+ if (!hasOneof(oneofDescriptor)) {
+ // If no field is set in the Oneof, skip all the fields in the Oneof
+ continue;
}
+ // Get the pointer to the only field which is set in the Oneof
+ field = getOneofFieldDescriptor(oneofDescriptor);
} else {
- if (hasField(field)) {
- result.put(field, getField(field));
+ // If we are not in a Oneof, we need to check if the field is set and if it is repeated
+ if (field.isRepeated()) {
+ final List<?> value = (List<?>) getField(field);
+ if (!value.isEmpty()) {
+ result.put(field, value);
+ }
+ continue;
+ }
+ if (!hasField(field)) {
+ continue;
}
}
+ // Add the field to the map
+ result.put(field, getField(field));
}
return result;
}
@@ -2696,4 +2741,38 @@ public abstract class GeneratedMessage extends AbstractMessage
return (Extension<MessageType, T>) extension;
}
+
+ protected static int computeStringSize(final int fieldNumber, final Object value) {
+ if (value instanceof String) {
+ return CodedOutputStream.computeStringSize(fieldNumber, (String) value);
+ } else {
+ return CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) value);
+ }
+ }
+
+ protected static int computeStringSizeNoTag(final Object value) {
+ if (value instanceof String) {
+ return CodedOutputStream.computeStringSizeNoTag((String) value);
+ } else {
+ return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
+ }
+ }
+
+ protected static void writeString(
+ CodedOutputStream output, final int fieldNumber, final Object value) throws IOException {
+ if (value instanceof String) {
+ output.writeString(fieldNumber, (String) value);
+ } else {
+ output.writeBytes(fieldNumber, (ByteString) value);
+ }
+ }
+
+ protected static void writeStringNoTag(
+ CodedOutputStream output, final Object value) throws IOException {
+ if (value instanceof String) {
+ output.writeStringNoTag((String) value);
+ } else {
+ output.writeBytesNoTag((ByteString) value);
+ }
+ }
}
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index bd6bc463..a535b718 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -48,7 +48,6 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
/**
* Lite version of {@link GeneratedMessage}.
@@ -60,24 +59,6 @@ public abstract class GeneratedMessageLite<
BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>>
extends AbstractMessageLite
implements Serializable {
-
- /**
- * Holds all the {@link PrototypeHolder}s for loaded classes.
- */
- // TODO(dweis): Consider different concurrency values.
- // TODO(dweis): This will prevent garbage collection of the class loader.
- // Ideally we'd use something like ClassValue but that's Java 7 only.
- private static final Map<Class<?>, PrototypeHolder<?, ?>> PROTOTYPE_MAP =
- new ConcurrentHashMap<Class<?>, PrototypeHolder<?, ?>>();
-
- // For use by generated code only.
- protected static <
- MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
- BuilderType extends GeneratedMessageLite.Builder<
- MessageType, BuilderType>> void onLoad(Class<MessageType> clazz,
- PrototypeHolder<MessageType, BuilderType> protoTypeHolder) {
- PROTOTYPE_MAP.put(clazz, protoTypeHolder);
- }
private static final long serialVersionUID = 1L;
@@ -90,20 +71,17 @@ public abstract class GeneratedMessageLite<
@SuppressWarnings("unchecked") // Guaranteed by runtime.
public final Parser<MessageType> getParserForType() {
- return (Parser<MessageType>) PROTOTYPE_MAP
- .get(getClass()).getParserForType();
+ return (Parser<MessageType>) dynamicMethod(MethodToInvoke.GET_PARSER);
}
@SuppressWarnings("unchecked") // Guaranteed by runtime.
public final MessageType getDefaultInstanceForType() {
- return (MessageType) PROTOTYPE_MAP
- .get(getClass()).getDefaultInstanceForType();
+ return (MessageType) dynamicMethod(MethodToInvoke.GET_DEFAULT_INSTANCE);
}
@SuppressWarnings("unchecked") // Guaranteed by runtime.
public final BuilderType newBuilderForType() {
- return (BuilderType) PROTOTYPE_MAP
- .get(getClass()).newBuilderForType();
+ return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER);
}
/**
@@ -141,7 +119,9 @@ public abstract class GeneratedMessageLite<
MERGE_FROM,
MAKE_IMMUTABLE,
NEW_INSTANCE,
- NEW_BUILDER;
+ NEW_BUILDER,
+ GET_DEFAULT_INSTANCE,
+ GET_PARSER;
}
/**
@@ -168,9 +148,21 @@ public abstract class GeneratedMessageLite<
* <p>
* For use by generated code only.
*/
- protected abstract Object dynamicMethod(
- MethodToInvoke method,
- Object... args);
+ protected abstract Object dynamicMethod(MethodToInvoke method, Object arg0, Object arg1);
+
+ /**
+ * Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding.
+ */
+ protected Object dynamicMethod(MethodToInvoke method, Object arg0) {
+ return dynamicMethod(method, arg0, null);
+ }
+
+ /**
+ * Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding.
+ */
+ protected Object dynamicMethod(MethodToInvoke method) {
+ return dynamicMethod(method, null, null);
+ }
/**
* Merge some unknown fields into the {@link UnknownFieldSetLite} for this
@@ -1059,18 +1051,22 @@ public abstract class GeneratedMessageLite<
@SuppressWarnings("unchecked")
protected Object readResolve() throws ObjectStreamException {
try {
- Class messageClass = Class.forName(messageClassName);
- Parser<?> parser =
- (Parser<?>) messageClass.getField("PARSER").get(null);
- return parser.parsePartialFrom(asBytes);
+ Class<?> messageClass = Class.forName(messageClassName);
+ java.lang.reflect.Field defaultInstanceField =
+ messageClass.getDeclaredField("DEFAULT_INSTANCE");
+ defaultInstanceField.setAccessible(true);
+ MessageLite defaultInstance = (MessageLite) defaultInstanceField.get(null);
+ return defaultInstance.newBuilderForType()
+ .mergeFrom(asBytes)
+ .buildPartial();
} catch (ClassNotFoundException e) {
- throw new RuntimeException("Unable to find proto buffer class", e);
+ throw new RuntimeException("Unable to find proto buffer class: " + messageClassName, e);
} catch (NoSuchFieldException e) {
- throw new RuntimeException("Unable to find PARSER", e);
+ throw new RuntimeException("Unable to find DEFAULT_INSTANCE in " + messageClassName, e);
} catch (SecurityException e) {
- throw new RuntimeException("Unable to call PARSER", e);
+ throw new RuntimeException("Unable to call DEFAULT_INSTANCE in " + messageClassName, e);
} catch (IllegalAccessException e) {
- throw new RuntimeException("Unable to call parseFrom method", e);
+ throw new RuntimeException("Unable to call parsePartialFrom", e);
} catch (InvalidProtocolBufferException e) {
throw new RuntimeException("Unable to understand proto buffer", e);
}
@@ -1103,45 +1099,6 @@ public abstract class GeneratedMessageLite<
return (GeneratedExtension<MessageType, T>) extension;
}
-
- /**
- * Represents the state needed to implement *ForType methods. Generated code
- * must provide a static singleton instance by adding it with
- * {@link GeneratedMessageLite#onLoad(Class, PrototypeHolder)} on class load.
- * <ul>
- * <li>{@link #getDefaultInstanceForType()}
- * <li>{@link #getParserForType()}
- * <li>{@link #newBuilderForType()}
- * </ul>
- * This allows us to trade three generated methods for a static Map.
- */
- protected static class PrototypeHolder<
- MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
- BuilderType extends GeneratedMessageLite.Builder<
- MessageType, BuilderType>> {
-
- private final MessageType defaultInstance;
- private final Parser<MessageType> parser;
-
- public PrototypeHolder(
- MessageType defaultInstance, Parser<MessageType> parser) {
- this.defaultInstance = defaultInstance;
- this.parser = parser;
- }
-
- public MessageType getDefaultInstanceForType() {
- return defaultInstance;
- }
-
- public Parser<MessageType> getParserForType() {
- return parser;
- }
-
- @SuppressWarnings("unchecked") // Guaranteed by runtime.
- public BuilderType newBuilderForType() {
- return (BuilderType) defaultInstance.toBuilder();
- }
- }
/**
* A static helper method for checking if a message is initialized, optionally memoizing.
diff --git a/java/src/main/java/com/google/protobuf/Internal.java b/java/src/main/java/com/google/protobuf/Internal.java
index 20054b79..11901998 100644
--- a/java/src/main/java/com/google/protobuf/Internal.java
+++ b/java/src/main/java/com/google/protobuf/Internal.java
@@ -31,6 +31,7 @@
package com.google.protobuf;
import java.io.IOException;
+import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.AbstractList;
@@ -155,8 +156,8 @@ public class Internal {
* but currently (2011) still accepts 3-byte surrogate character
* byte sequences.
*
- * <p>See the Unicode Standard,</br>
- * Table 3-6. <em>UTF-8 Bit Distribution</em>,</br>
+ * <p>See the Unicode Standard,<br>
+ * Table 3-6. <em>UTF-8 Bit Distribution</em>,<br>
* Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
*
* <p>As of 2011-02, this method simply returns the result of {@link
@@ -358,6 +359,17 @@ public class Internal {
}
}
+ @SuppressWarnings("unchecked")
+ public static <T extends MessageLite> T getDefaultInstance(Class<T> clazz) {
+ try {
+ Method method = clazz.getMethod("getDefaultInstance");
+ return (T) method.invoke(method);
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Failed to get default instance for " + clazz, e);
+ }
+ }
+
/**
* An empty byte array constant used in generated code.
*/
@@ -375,7 +387,7 @@ public class Internal {
/**
- * Provides an immutable view of List<T> around a List<F>.
+ * Provides an immutable view of {@code List<T>} around a {@code List<F>}.
*
* Protobuf internal. Used in protobuf generated code only.
*/
@@ -407,7 +419,8 @@ public class Internal {
}
/**
- * Wrap around a Map<K, RealValue> and provide a Map<K, V> interface.
+ * Wrap around a {@code Map<K, RealValue>} and provide a {@code Map<K, V>}
+ * interface.
*/
public static class MapAdapter<K, V, RealValue> extends AbstractMap<K, V> {
/**
@@ -564,12 +577,12 @@ public class Internal {
int getInt(int index);
/**
- * Like {@link #add(Integer)} but more efficient in that it doesn't box the element.
+ * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
*/
void addInt(int element);
/**
- * Like {@link #set(int, Integer)} but more efficient in that it doesn't box the element.
+ * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
*/
int setInt(int index, int element);
}
@@ -586,12 +599,12 @@ public class Internal {
boolean getBoolean(int index);
/**
- * Like {@link #add(Boolean)} but more efficient in that it doesn't box the element.
+ * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
*/
void addBoolean(boolean element);
/**
- * Like {@link #set(int, Boolean)} but more efficient in that it doesn't box the element.
+ * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
*/
boolean setBoolean(int index, boolean element);
}
@@ -608,12 +621,12 @@ public class Internal {
long getLong(int index);
/**
- * Like {@link #add(Long)} but more efficient in that it doesn't box the element.
+ * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
*/
void addLong(long element);
/**
- * Like {@link #set(int, Long)} but more efficient in that it doesn't box the element.
+ * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
*/
long setLong(int index, long element);
}
@@ -630,12 +643,12 @@ public class Internal {
double getDouble(int index);
/**
- * Like {@link #add(Double)} but more efficient in that it doesn't box the element.
+ * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
*/
void addDouble(double element);
/**
- * Like {@link #set(int, Double)} but more efficient in that it doesn't box the element.
+ * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
*/
double setDouble(int index, double element);
}
@@ -652,12 +665,12 @@ public class Internal {
float getFloat(int index);
/**
- * Like {@link #add(Float)} but more efficient in that it doesn't box the element.
+ * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
*/
void addFloat(float element);
/**
- * Like {@link #set(int, Float)} but more efficient in that it doesn't box the element.
+ * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
*/
float setFloat(int index, float element);
}
diff --git a/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
index 367fa23b..0a761052 100644
--- a/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
+++ b/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
@@ -69,7 +69,7 @@ public class InvalidProtocolBufferException extends IOException {
static InvalidProtocolBufferException truncatedMessage() {
return new InvalidProtocolBufferException(
"While parsing a protocol message, the input ended unexpectedly " +
- "in the middle of a field. This could mean either than the " +
+ "in the middle of a field. This could mean either that the " +
"input has been truncated or that an embedded message " +
"misreported its own length.");
}
diff --git a/java/src/main/java/com/google/protobuf/LazyStringArrayList.java b/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
index a2997e1c..c3be3cca 100644
--- a/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
+++ b/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
@@ -215,6 +215,11 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
modCount++;
}
+ @Override
+ public Object getRaw(int index) {
+ return list.get(index);
+ }
+
// @Override
public ByteString getByteString(int index) {
Object o = list.get(index);
diff --git a/java/src/main/java/com/google/protobuf/LazyStringList.java b/java/src/main/java/com/google/protobuf/LazyStringList.java
index 235126b6..3eeedca1 100644
--- a/java/src/main/java/com/google/protobuf/LazyStringList.java
+++ b/java/src/main/java/com/google/protobuf/LazyStringList.java
@@ -56,7 +56,18 @@ public interface LazyStringList extends ProtocolStringList {
* ({@code index < 0 || index >= size()})
*/
ByteString getByteString(int index);
-
+
+ /**
+ * Returns the element at the specified position in this list as an Object
+ * that will either be a String or a ByteString.
+ *
+ * @param index index of the element to return
+ * @return the element at the specified position in this list
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * ({@code index < 0 || index >= size()})
+ */
+ Object getRaw(int index);
+
/**
* Returns the element at the specified position in this list as byte[].
*
diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java
index fa0265e2..9516d71f 100644
--- a/java/src/main/java/com/google/protobuf/Message.java
+++ b/java/src/main/java/com/google/protobuf/Message.java
@@ -121,6 +121,9 @@ public interface Message extends MessageLite, MessageOrBuilder {
* 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++.
*/
diff --git a/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java b/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
index be737b1a..f91cdbce 100644
--- a/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
+++ b/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
@@ -73,7 +73,7 @@ public class RepeatedFieldBuilder
private GeneratedMessage.BuilderParent parent;
// List of messages. Never null. It may be immutable, in which case
- // isMessagesListImmutable will be true. See note below.
+ // isMessagesListMutable will be false. See note below.
private List<MType> messages;
// Whether messages is an mutable array that can be modified.
diff --git a/java/src/main/java/com/google/protobuf/RopeByteString.java b/java/src/main/java/com/google/protobuf/RopeByteString.java
index 4f3eb127..2c332624 100644
--- a/java/src/main/java/com/google/protobuf/RopeByteString.java
+++ b/java/src/main/java/com/google/protobuf/RopeByteString.java
@@ -56,7 +56,7 @@ import java.util.Stack;
* michael plass
*
* <p>The algorithms described in the paper have been implemented for character
- * strings in {@link com.google.common.string.Rope} and in the c++ class {@code
+ * strings in {@code com.google.common.string.Rope} and in the c++ class {@code
* cord.cc}.
*
* <p>Fundamentally the Rope algorithm represents the collection of pieces as a
diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java
index a79ce559..b4f4ce78 100644
--- a/java/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/src/main/java/com/google/protobuf/TextFormat.java
@@ -1175,12 +1175,12 @@ public final class TextFormat {
* Determines if repeated values for non-repeated fields and
* oneofs are permitted. For example, given required/optional field "foo"
* and a oneof containing "baz" and "qux":
- * <li>
- * <ul>"foo: 1 foo: 2"
- * <ul>"baz: 1 qux: 2"
- * <ul>merging "foo: 2" into a proto in which foo is already set, or
- * <ul>merging "qux: 2" into a proto in which baz is already set.
- * </li>
+ * <ul>
+ * <li>"foo: 1 foo: 2"
+ * <li>"baz: 1 qux: 2"
+ * <li>merging "foo: 2" into a proto in which foo is already set, or
+ * <li>merging "qux: 2" into a proto in which baz is already set.
+ * </ul>
*/
public enum SingularOverwritePolicy {
/** The last value is retained. */
diff --git a/java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java b/java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
index 7ea84022..45d5fc35 100644
--- a/java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
+++ b/java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
@@ -31,6 +31,7 @@
package com.google.protobuf;
import java.io.IOException;
+import java.util.Arrays;
/**
* {@code UnknownFieldSetLite} is used to keep track of fields which were seen
@@ -45,8 +46,11 @@ import java.io.IOException;
*/
public final class UnknownFieldSetLite {
+ private static final int[] EMPTY_INT_ARRAY = new int[0];
+ private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
+
private static final UnknownFieldSetLite DEFAULT_INSTANCE =
- new UnknownFieldSetLite(ByteString.EMPTY);
+ new UnknownFieldSetLite(0, EMPTY_INT_ARRAY, EMPTY_OBJECT_ARRAY);
/**
* Get an empty {@code UnknownFieldSetLite}.
@@ -71,19 +75,41 @@ public final class UnknownFieldSetLite {
* {@code second}.
*/
static UnknownFieldSetLite concat(UnknownFieldSetLite first, UnknownFieldSetLite second) {
- return new UnknownFieldSetLite(first.byteString.concat(second.byteString));
+ int count = first.count + second.count;
+ int[] tags = Arrays.copyOf(first.tags, count);
+ System.arraycopy(second.tags, 0, tags, first.count, second.count);
+ Object[] objects = Arrays.copyOf(first.objects, count);
+ System.arraycopy(second.objects, 0, objects, first.count, second.count);
+ return new UnknownFieldSetLite(count, tags, objects);
}
-
+
+ /**
+ * The number of elements in the set.
+ */
+ private int count;
+
+ /**
+ * The tag numbers for the elements in the set.
+ */
+ private int[] tags;
+
/**
- * The internal representation of the unknown fields.
+ * The boxed values of the elements in the set.
*/
- private final ByteString byteString;
+ private Object[] objects;
+
+ /**
+ * The lazily computed serialized size of the set.
+ */
+ private int memoizedSerializedSize = -1;
/**
- * Constructs the {@code UnknownFieldSetLite} as a thin wrapper around {@link ByteString}.
+ * Constructs the {@code UnknownFieldSetLite}.
*/
- private UnknownFieldSetLite(ByteString byteString) {
- this.byteString = byteString;
+ private UnknownFieldSetLite(int count, int[] tags, Object[] objects) {
+ this.count = count;
+ this.tags = tags;
+ this.objects = objects;
}
/**
@@ -92,17 +118,73 @@ public final class UnknownFieldSetLite {
* <p>For use by generated code only.
*/
public void writeTo(CodedOutputStream output) throws IOException {
- output.writeRawBytes(byteString);
+ for (int i = 0; i < count; i++) {
+ int tag = tags[i];
+ int fieldNumber = WireFormat.getTagFieldNumber(tag);
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ output.writeUInt64(fieldNumber, (Long) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_FIXED32:
+ output.writeFixed32(fieldNumber, (Integer) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_FIXED64:
+ output.writeFixed64(fieldNumber, (Long) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ output.writeBytes(fieldNumber, (ByteString) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_START_GROUP:
+ output.writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
+ ((UnknownFieldSetLite) objects[i]).writeTo(output);
+ output.writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
+ break;
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
}
-
/**
* Get the number of bytes required to encode this set.
*
* <p>For use by generated code only.
*/
public int getSerializedSize() {
- return byteString.size();
+ int size = memoizedSerializedSize;
+ if (size != -1) {
+ return size;
+ }
+
+ size = 0;
+ for (int i = 0; i < count; i++) {
+ int tag = tags[i];
+ int fieldNumber = WireFormat.getTagFieldNumber(tag);
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ size += CodedOutputStream.computeUInt64Size(fieldNumber, (Long) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_FIXED32:
+ size += CodedOutputStream.computeFixed32Size(fieldNumber, (Integer) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_FIXED64:
+ size += CodedOutputStream.computeFixed64Size(fieldNumber, (Long) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ size += CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_START_GROUP:
+ size += CodedOutputStream.computeTagSize(fieldNumber) * 2
+ + ((UnknownFieldSetLite) objects[i]).getSerializedSize();
+ break;
+ default:
+ throw new IllegalStateException(InvalidProtocolBufferException.invalidWireType());
+ }
+ }
+
+ memoizedSerializedSize = size;
+
+ return size;
}
@Override
@@ -111,16 +193,34 @@ public final class UnknownFieldSetLite {
return true;
}
- if (obj instanceof UnknownFieldSetLite) {
- return byteString.equals(((UnknownFieldSetLite) obj).byteString);
+ if (obj == null) {
+ return false;
+ }
+
+ if (!(obj instanceof UnknownFieldSetLite)) {
+ return false;
+ }
+
+ UnknownFieldSetLite other = (UnknownFieldSetLite) obj;
+ if (count != other.count
+ // TODO(dweis): Only have to compare up to count but at worst 2x worse than we need to do.
+ || !Arrays.equals(tags, other.tags)
+ || !Arrays.deepEquals(objects, other.objects)) {
+ return false;
}
- return false;
+ return true;
}
@Override
public int hashCode() {
- return byteString.hashCode();
+ int hashCode = 17;
+
+ hashCode = 31 * hashCode + count;
+ hashCode = 31 * hashCode + Arrays.hashCode(tags);
+ hashCode = 31 * hashCode + Arrays.deepHashCode(objects);
+
+ return hashCode;
}
/**
@@ -131,28 +231,49 @@ public final class UnknownFieldSetLite {
* <p>For use by generated code only.
*/
public static final class Builder {
+
+ // Arbitrarily chosen.
+ // TODO(dweis): Tune this number?
+ private static final int MIN_CAPACITY = 8;
+
+ private int count = 0;
+ private int[] tags = EMPTY_INT_ARRAY;
+ private Object[] objects = EMPTY_OBJECT_ARRAY;
- private ByteString.Output byteStringOutput;
- private CodedOutputStream output;
private boolean built;
/**
- * Constructs a {@code Builder}. Lazily initialized by
- * {@link #ensureInitializedButNotBuilt()}.
+ * Constructs a {@code Builder}.
*/
private Builder() {}
/**
* Ensures internal state is initialized for use.
*/
- private void ensureInitializedButNotBuilt() {
+ private void ensureNotBuilt() {
if (built) {
throw new IllegalStateException("Do not reuse UnknownFieldSetLite Builders.");
}
-
- if (output == null && byteStringOutput == null) {
- byteStringOutput = ByteString.newOutput(100 /* initialCapacity */);
- output = CodedOutputStream.newInstance(byteStringOutput);
+ }
+
+ private void storeField(int tag, Object value) {
+ ensureCapacity();
+
+ tags[count] = tag;
+ objects[count] = value;
+ count++;
+ }
+
+ /**
+ * Ensures that our arrays are long enough to store more metadata.
+ */
+ private void ensureCapacity() {
+ if (count == tags.length) {
+ int increment = count < (MIN_CAPACITY / 2) ? MIN_CAPACITY : count >> 1;
+ int newLength = count + increment;
+
+ tags = Arrays.copyOf(tags, newLength);
+ objects = Arrays.copyOf(objects, newLength);
}
}
@@ -166,31 +287,28 @@ public final class UnknownFieldSetLite {
*/
public boolean mergeFieldFrom(final int tag, final CodedInputStream input)
throws IOException {
- ensureInitializedButNotBuilt();
+ ensureNotBuilt();
final int fieldNumber = WireFormat.getTagFieldNumber(tag);
switch (WireFormat.getTagWireType(tag)) {
case WireFormat.WIRETYPE_VARINT:
- output.writeUInt64(fieldNumber, input.readInt64());
+ storeField(tag, input.readInt64());
return true;
case WireFormat.WIRETYPE_FIXED32:
- output.writeFixed32(fieldNumber, input.readFixed32());
+ storeField(tag, input.readFixed32());
return true;
case WireFormat.WIRETYPE_FIXED64:
- output.writeFixed64(fieldNumber, input.readFixed64());
+ storeField(tag, input.readFixed64());
return true;
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
- output.writeBytes(fieldNumber, input.readBytes());
+ storeField(tag, input.readBytes());
return true;
case WireFormat.WIRETYPE_START_GROUP:
final Builder subBuilder = newBuilder();
subBuilder.mergeFrom(input);
input.checkLastTagWas(
WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
-
- output.writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
- subBuilder.build().writeTo(output);
- output.writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
+ storeField(tag, subBuilder.build());
return true;
case WireFormat.WIRETYPE_END_GROUP:
return false;
@@ -210,12 +328,10 @@ public final class UnknownFieldSetLite {
if (fieldNumber == 0) {
throw new IllegalArgumentException("Zero is not a valid field number.");
}
- ensureInitializedButNotBuilt();
- try {
- output.writeUInt64(fieldNumber, value);
- } catch (IOException e) {
- // Should never happen.
- }
+ ensureNotBuilt();
+
+ storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_VARINT), (long) value);
+
return this;
}
@@ -229,11 +345,24 @@ public final class UnknownFieldSetLite {
if (fieldNumber == 0) {
throw new IllegalArgumentException("Zero is not a valid field number.");
}
- ensureInitializedButNotBuilt();
- try {
- output.writeBytes(fieldNumber, value);
- } catch (IOException e) {
- // Should never happen.
+ ensureNotBuilt();
+
+ storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED), value);
+
+ return this;
+ }
+
+ /**
+ * Parse an entire message from {@code input} and merge its fields into
+ * this set.
+ */
+ private Builder mergeFrom(final CodedInputStream input) throws IOException {
+ // Ensures initialization in mergeFieldFrom.
+ while (true) {
+ final int tag = input.readTag();
+ if (tag == 0 || !mergeFieldFrom(tag, input)) {
+ break;
+ }
}
return this;
}
@@ -254,44 +383,12 @@ public final class UnknownFieldSetLite {
}
built = true;
-
- final UnknownFieldSetLite result;
- // If we were never initialized, no data was written.
- if (output == null) {
- result = getDefaultInstance();
- } else {
- try {
- output.flush();
- } catch (IOException e) {
- // Should never happen.
- }
- ByteString byteString = byteStringOutput.toByteString();
- if (byteString.isEmpty()) {
- result = getDefaultInstance();
- } else {
- result = new UnknownFieldSetLite(byteString);
- }
+
+ if (count == 0) {
+ return DEFAULT_INSTANCE;
}
- // Allow for garbage collection.
- output = null;
- byteStringOutput = null;
- return result;
- }
-
- /**
- * Parse an entire message from {@code input} and merge its fields into
- * this set.
- */
- private Builder mergeFrom(final CodedInputStream input) throws IOException {
- // Ensures initialization in mergeFieldFrom.
- while (true) {
- final int tag = input.readTag();
- if (tag == 0 || !mergeFieldFrom(tag, input)) {
- break;
- }
- }
- return this;
+ return new UnknownFieldSetLite(count, tags, objects);
}
}
}
diff --git a/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java b/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
index 5cc005df..5257c5a2 100644
--- a/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
+++ b/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
@@ -57,6 +57,11 @@ public class UnmodifiableLazyStringList extends AbstractList<String>
public String get(int index) {
return list.get(index);
}
+
+ @Override
+ public Object getRaw(int index) {
+ return list.getRaw(index);
+ }
@Override
public int size() {
diff --git a/java/src/main/java/com/google/protobuf/Utf8.java b/java/src/main/java/com/google/protobuf/Utf8.java
index 4271b41b..0699778f 100644
--- a/java/src/main/java/com/google/protobuf/Utf8.java
+++ b/java/src/main/java/com/google/protobuf/Utf8.java
@@ -66,6 +66,12 @@ package com.google.protobuf;
*/
final class Utf8 {
private Utf8() {}
+
+ /**
+ * Maximum number of bytes per Java UTF-16 char in UTF-8.
+ * @see java.nio.charset.CharsetEncoder#maxBytesPerChar()
+ */
+ static final int MAX_BYTES_PER_CHAR = 3;
/**
* State value indicating that the byte sequence is well-formed and
@@ -346,4 +352,130 @@ final class Utf8 {
default: throw new AssertionError();
}
}
+
+
+ // These UTF-8 handling methods are copied from Guava's Utf8 class with a modification to throw
+ // a protocol buffer local exception. This exception is then caught in CodedOutputStream so it can
+ // fallback to more lenient behavior.
+
+ static class UnpairedSurrogateException extends IllegalArgumentException {
+
+ private UnpairedSurrogateException(int index) {
+ super("Unpaired surrogate at index " + index);
+ }
+ }
+
+ /**
+ * Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string,
+ * this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in
+ * both time and space.
+ *
+ * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
+ * surrogates)
+ */
+ static int encodedLength(CharSequence sequence) {
+ // Warning to maintainers: this implementation is highly optimized.
+ int utf16Length = sequence.length();
+ int utf8Length = utf16Length;
+ int i = 0;
+
+ // This loop optimizes for pure ASCII.
+ while (i < utf16Length && sequence.charAt(i) < 0x80) {
+ i++;
+ }
+
+ // This loop optimizes for chars less than 0x800.
+ for (; i < utf16Length; i++) {
+ char c = sequence.charAt(i);
+ if (c < 0x800) {
+ utf8Length += ((0x7f - c) >>> 31); // branch free!
+ } else {
+ utf8Length += encodedLengthGeneral(sequence, i);
+ break;
+ }
+ }
+
+ if (utf8Length < utf16Length) {
+ // Necessary and sufficient condition for overflow because of maximum 3x expansion
+ throw new IllegalArgumentException("UTF-8 length does not fit in int: "
+ + (utf8Length + (1L << 32)));
+ }
+ return utf8Length;
+ }
+
+ private static int encodedLengthGeneral(CharSequence sequence, int start) {
+ int utf16Length = sequence.length();
+ int utf8Length = 0;
+ for (int i = start; i < utf16Length; i++) {
+ char c = sequence.charAt(i);
+ if (c < 0x800) {
+ utf8Length += (0x7f - c) >>> 31; // branch free!
+ } else {
+ utf8Length += 2;
+ // jdk7+: if (Character.isSurrogate(c)) {
+ if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) {
+ // Check that we have a well-formed surrogate pair.
+ int cp = Character.codePointAt(sequence, i);
+ if (cp < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+ throw new UnpairedSurrogateException(i);
+ }
+ i++;
+ }
+ }
+ }
+ return utf8Length;
+ }
+
+ static int encode(CharSequence sequence, byte[] bytes, int offset, int length) {
+ int utf16Length = sequence.length();
+ int j = offset;
+ int i = 0;
+ int limit = offset + length;
+ // Designed to take advantage of
+ // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+ for (char c; i < utf16Length && i + j < limit && (c = sequence.charAt(i)) < 0x80; i++) {
+ bytes[j + i] = (byte) c;
+ }
+ if (i == utf16Length) {
+ return j + utf16Length;
+ }
+ j += i;
+ for (char c; i < utf16Length; i++) {
+ c = sequence.charAt(i);
+ if (c < 0x80 && j < limit) {
+ bytes[j++] = (byte) c;
+ } else if (c < 0x800 && j <= limit - 2) { // 11 bits, two UTF-8 bytes
+ bytes[j++] = (byte) ((0xF << 6) | (c >>> 6));
+ bytes[j++] = (byte) (0x80 | (0x3F & c));
+ } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) && j <= limit - 3) {
+ // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+ bytes[j++] = (byte) ((0xF << 5) | (c >>> 12));
+ bytes[j++] = (byte) (0x80 | (0x3F & (c >>> 6)));
+ bytes[j++] = (byte) (0x80 | (0x3F & c));
+ } else if (j <= limit - 4) {
+ // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8 bytes
+ final char low;
+ if (i + 1 == sequence.length()
+ || !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) {
+ throw new UnpairedSurrogateException((i - 1));
+ }
+ int codePoint = Character.toCodePoint(c, low);
+ bytes[j++] = (byte) ((0xF << 4) | (codePoint >>> 18));
+ bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 12)));
+ bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 6)));
+ bytes[j++] = (byte) (0x80 | (0x3F & codePoint));
+ } else {
+ // If we are surrogates and we're not a surrogate pair, always throw an
+ // IllegalArgumentException instead of an ArrayOutOfBoundsException.
+ if ((Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE)
+ && (i + 1 == sequence.length()
+ || !Character.isSurrogatePair(c, sequence.charAt(i + 1)))) {
+ throw new UnpairedSurrogateException(i);
+ }
+ throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j);
+ }
+ }
+ return j;
+ }
+ // End Guava UTF-8 methods.
}
diff --git a/java/src/main/java/com/google/protobuf/WireFormat.java b/java/src/main/java/com/google/protobuf/WireFormat.java
index ba83b666..8dbe1ae3 100644
--- a/java/src/main/java/com/google/protobuf/WireFormat.java
+++ b/java/src/main/java/com/google/protobuf/WireFormat.java
@@ -58,7 +58,7 @@ public final class WireFormat {
static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1;
/** Given a tag value, determines the wire type (the lower 3 bits). */
- static int getTagWireType(final int tag) {
+ public static int getTagWireType(final int tag) {
return tag & TAG_TYPE_MASK;
}
diff --git a/java/src/test/java/com/google/protobuf/AnyTest.java b/java/src/test/java/com/google/protobuf/AnyTest.java
new file mode 100644
index 00000000..e169f69d
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/AnyTest.java
@@ -0,0 +1,92 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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 any_test.AnyTestProto.TestAny;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for Any message.
+ */
+public class AnyTest extends TestCase {
+ public void testAnyGeneratedApi() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+
+ TestAny container = TestAny.newBuilder()
+ .setValue(Any.pack(message)).build();
+
+ assertTrue(container.getValue().is(TestAllTypes.class));
+ assertFalse(container.getValue().is(TestAny.class));
+
+ TestAllTypes result = container.getValue().unpack(TestAllTypes.class);
+ TestUtil.assertAllFieldsSet(result);
+
+
+ // Unpacking to a wrong type will throw an exception.
+ try {
+ TestAny wrongMessage = container.getValue().unpack(TestAny.class);
+ fail("Exception is expected.");
+ } catch (InvalidProtocolBufferException e) {
+ // expected.
+ }
+
+ // Test that unpacking throws an exception if parsing fails.
+ TestAny.Builder containerBuilder = container.toBuilder();
+ containerBuilder.getValueBuilder().setValue(
+ ByteString.copyFrom(new byte[]{0x11}));
+ container = containerBuilder.build();
+ try {
+ TestAllTypes parsingFailed = container.getValue().unpack(TestAllTypes.class);
+ fail("Exception is expected.");
+ } catch (InvalidProtocolBufferException e) {
+ // expected.
+ }
+ }
+
+ public void testCachedUnpackResult() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+
+ TestAny container = TestAny.newBuilder()
+ .setValue(Any.pack(message)).build();
+
+ assertTrue(container.getValue().is(TestAllTypes.class));
+
+ TestAllTypes result1 = container.getValue().unpack(TestAllTypes.class);
+ TestAllTypes result2 = container.getValue().unpack(TestAllTypes.class);
+ assertTrue(result1 == result2);
+ }
+}
diff --git a/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java b/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java
index 1562a1a6..447e6ef3 100644
--- a/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java
+++ b/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java
@@ -85,6 +85,7 @@ public class BoundedByteStringTest extends LiteralByteStringTest {
testString.substring(2, testString.length() - 6), roundTripString);
}
+ @Override
public void testJavaSerialization() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(out);
diff --git a/java/src/test/java/com/google/protobuf/CheckUtf8Test.java b/java/src/test/java/com/google/protobuf/CheckUtf8Test.java
index 6470e9ca..3d6381c9 100644
--- a/java/src/test/java/com/google/protobuf/CheckUtf8Test.java
+++ b/java/src/test/java/com/google/protobuf/CheckUtf8Test.java
@@ -58,8 +58,7 @@ public class CheckUtf8Test extends TestCase {
public void testParseRequiredStringWithGoodUtf8() throws Exception {
ByteString serialized =
BytesWrapper.newBuilder().setReq(UTF8_BYTE_STRING).build().toByteString();
- assertEquals(UTF8_BYTE_STRING_TEXT,
- StringWrapper.PARSER.parseFrom(serialized).getReq());
+ assertEquals(UTF8_BYTE_STRING_TEXT, StringWrapper.parser().parseFrom(serialized).getReq());
}
public void testBuildRequiredStringWithBadUtf8() throws Exception {
@@ -93,7 +92,7 @@ public class CheckUtf8Test extends TestCase {
ByteString serialized =
BytesWrapper.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteString();
try {
- StringWrapper.PARSER.parseFrom(serialized);
+ StringWrapper.parser().parseFrom(serialized);
fail("Expected InvalidProtocolBufferException for non UTF-8 byte string.");
} catch (InvalidProtocolBufferException exception) {
assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
@@ -131,7 +130,7 @@ public class CheckUtf8Test extends TestCase {
ByteString serialized =
BytesWrapperSize.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteString();
try {
- StringWrapperSize.PARSER.parseFrom(serialized);
+ StringWrapperSize.parser().parseFrom(serialized);
fail("Expected InvalidProtocolBufferException for non UTF-8 byte string.");
} catch (InvalidProtocolBufferException exception) {
assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
diff --git a/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java b/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
index 365789c0..360e759e 100644
--- a/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
+++ b/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
@@ -40,6 +40,7 @@ import junit.framework.TestCase;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -325,10 +326,41 @@ public class CodedOutputStreamTest extends TestCase {
for (int i = 0; i < 1024; ++i) {
codedStream.writeRawBytes(value, 0, value.length);
}
+ 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);
+ 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);
- assertEquals(value.length * 1024, codedStream.getTotalBytesWritten());
+
+ // Verify that the total bytes written is correct
+ assertEquals((value.length * 1024) + stringSize, codedStream.getTotalBytesWritten());
+ }
+
+ // TODO(dweis): Write a comprehensive test suite for CodedOutputStream that covers more than just
+ // this case.
+ public void testWriteStringNoTag_fastpath() throws Exception {
+ int bufferSize = 153;
+ String threeBytesPer = "\u0981";
+ String string = threeBytesPer;
+ for (int i = 0; i < 50; i++) {
+ string += threeBytesPer;
+ }
+ // These checks ensure we will tickle the slower fast path.
+ assertEquals(1, CodedOutputStream.computeRawVarint32Size(string.length()));
+ assertEquals(
+ 2, CodedOutputStream.computeRawVarint32Size(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);
}
public void testWriteToByteBuffer() throws Exception {
@@ -398,4 +430,80 @@ public class CodedOutputStreamTest extends TestCase {
assertEqualBytes(bytes(0x02, 0x33, 0x44, 0x00), destination);
assertEquals(3, codedStream.getTotalBytesWritten());
}
+
+ public void testSerializeInvalidUtf8() throws Exception {
+ String[] invalidStrings = new String[] {
+ newString(Character.MIN_HIGH_SURROGATE),
+ "foobar" + newString(Character.MIN_HIGH_SURROGATE),
+ newString(Character.MIN_LOW_SURROGATE),
+ "foobar" + newString(Character.MIN_LOW_SURROGATE),
+ newString(Character.MIN_HIGH_SURROGATE, Character.MIN_HIGH_SURROGATE)
+ };
+
+ CodedOutputStream outputWithStream = CodedOutputStream.newInstance(new ByteArrayOutputStream());
+ CodedOutputStream outputWithArray = CodedOutputStream.newInstance(new byte[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);
+ }
+ }
+
+ private static String newString(char... chars) {
+ return new String(chars);
+ }
+
+ /** 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(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) {}
+ }
+ }
+
+ 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
+ };
+ 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
+ }
+ }
+
+ private void testEncodingOfString(char c, int length) throws Exception {
+ String fullString = fullString(c, length);
+ TestAllTypes testAllTypes = TestAllTypes.newBuilder()
+ .setOptionalString(fullString)
+ .build();
+ assertEquals(
+ fullString, TestAllTypes.parseFrom(testAllTypes.toByteArray()).getOptionalString());
+ }
+
+ private String fullString(char c, int length) {
+ char[] result = new char[length];
+ Arrays.fill(result, c);
+ return new String(result);
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/FieldPresenceTest.java b/java/src/test/java/com/google/protobuf/FieldPresenceTest.java
index acf2b023..eaeec0b8 100644
--- a/java/src/test/java/com/google/protobuf/FieldPresenceTest.java
+++ b/java/src/test/java/com/google/protobuf/FieldPresenceTest.java
@@ -142,6 +142,16 @@ public class FieldPresenceTest extends TestCase {
"OneofNestedMessage"));
}
+ public void testOneofEquals() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestAllTypes message1 = builder.build();
+ // Set message2's oneof_uint32 field to defalut value. The two
+ // messages should be different when check with oneof case.
+ builder.setOneofUint32(0);
+ TestAllTypes message2 = builder.build();
+ assertFalse(message1.equals(message2));
+ }
+
public void testFieldPresence() {
// Optional non-message fields set to their default value are treated the
// same way as not set.
diff --git a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index 2bd8d1a9..70812b95 100644
--- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -187,8 +187,7 @@ public class GeneratedMessageTest extends TestCase {
}
public void testParsedMessagesAreImmutable() throws Exception {
- TestAllTypes value = TestAllTypes.PARSER.parseFrom(
- TestUtil.getAllSet().toByteString());
+ TestAllTypes value = TestAllTypes.parser().parseFrom(TestUtil.getAllSet().toByteString());
assertIsUnmodifiable(value.getRepeatedInt32List());
assertIsUnmodifiable(value.getRepeatedInt64List());
assertIsUnmodifiable(value.getRepeatedUint32List());
diff --git a/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java b/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
index acd18003..0ef414aa 100644
--- a/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
+++ b/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
@@ -89,7 +89,7 @@ public class LazyStringEndToEndTest extends TestCase {
TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8,
ByteString.copyFrom(sink));
}
-
+
public void testCaching() {
String a = "a";
String b = "b";
@@ -106,24 +106,13 @@ public class LazyStringEndToEndTest extends TestCase {
assertSame(c, proto.getRepeatedString(1));
- // There's no way to directly observe that the ByteString is cached
- // correctly on serialization, but we can observe that it had to recompute
- // the string after serialization.
+ // Ensure serialization keeps strings cached.
proto.toByteString();
- String aPrime = proto.getOptionalString();
- assertNotSame(a, aPrime);
- assertEquals(a, aPrime);
- String bPrime = proto.getRepeatedString(0);
- assertNotSame(b, bPrime);
- assertEquals(b, bPrime);
- String cPrime = proto.getRepeatedString(1);
- assertNotSame(c, cPrime);
- assertEquals(c, cPrime);
// And now the string should stay cached.
- assertSame(aPrime, proto.getOptionalString());
- assertSame(bPrime, proto.getRepeatedString(0));
- assertSame(cPrime, proto.getRepeatedString(1));
+ assertSame(a, proto.getOptionalString());
+ assertSame(b, proto.getRepeatedString(0));
+ assertSame(c, proto.getRepeatedString(1));
}
public void testNoStringCachingIfOnlyBytesAccessed() throws Exception {
diff --git a/java/src/test/java/com/google/protobuf/LiteTest.java b/java/src/test/java/com/google/protobuf/LiteTest.java
index 8c3b5e5c..b1f298ff 100644
--- a/java/src/test/java/com/google/protobuf/LiteTest.java
+++ b/java/src/test/java/com/google/protobuf/LiteTest.java
@@ -42,6 +42,7 @@ 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 junit.framework.TestCase;
@@ -1400,6 +1401,8 @@ public class LiteTest extends TestCase {
assertEquals("hi", messageAfterBuild.getOneofString());
assertEquals(OneofFieldCase.ONEOF_UINT32, builder.getOneofFieldCase());
assertEquals(1, builder.getOneofUint32());
+ TestAllTypesLiteOrBuilder messageOrBuilder = builder;
+ assertEquals(OneofFieldCase.ONEOF_UINT32, messageOrBuilder.getOneofFieldCase());
TestAllExtensionsLite.Builder extendableMessageBuilder =
TestAllExtensionsLite.newBuilder();
diff --git a/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
index 958b6a7e..7dfda2ae 100644
--- a/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
+++ b/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
@@ -34,6 +34,7 @@ import junit.framework.TestCase;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
@@ -209,6 +210,62 @@ public class LiteralByteStringTest extends TestCase {
Arrays.equals(referenceBytes, myBuffer.array()));
}
+ public void testMarkSupported() {
+ InputStream stream = stringUnderTest.newInput();
+ assertTrue(classUnderTest + ".newInput() must support marking", stream.markSupported());
+ }
+
+ public void testMarkAndReset() throws IOException {
+ int fraction = stringUnderTest.size() / 3;
+
+ InputStream stream = stringUnderTest.newInput();
+ stream.mark(stringUnderTest.size()); // First, mark() the end.
+
+ skipFully(stream, fraction); // Skip a large fraction, but not all.
+ int available = stream.available();
+ assertTrue(
+ classUnderTest + ": after skipping to the 'middle', half the bytes are available",
+ (stringUnderTest.size() - fraction) == available);
+ stream.reset();
+
+ skipFully(stream, stringUnderTest.size()); // Skip to the end.
+ available = stream.available();
+ assertTrue(
+ classUnderTest + ": after skipping to the end, no more bytes are available",
+ 0 == available);
+ }
+
+ /**
+ * Discards {@code n} bytes of data from the input stream. This method
+ * will block until the full amount has been skipped. Does not close the
+ * stream.
+ * <p>Copied from com.google.common.io.ByteStreams to avoid adding dependency.
+ *
+ * @param in the input stream to read from
+ * @param n the number of bytes to skip
+ * @throws EOFException if this stream reaches the end before skipping all
+ * the bytes
+ * @throws IOException if an I/O error occurs, or the stream does not
+ * support skipping
+ */
+ static void skipFully(InputStream in, long n) throws IOException {
+ long toSkip = n;
+ while (n > 0) {
+ long amt = in.skip(n);
+ if (amt == 0) {
+ // Force a blocking read to avoid infinite loop
+ if (in.read() == -1) {
+ long skipped = toSkip - n;
+ throw new EOFException("reached end of stream after skipping "
+ + skipped + " bytes; " + toSkip + " bytes expected");
+ }
+ n--;
+ } else {
+ n -= amt;
+ }
+ }
+ }
+
public void testAsReadOnlyByteBuffer() {
ByteBuffer byteBuffer = stringUnderTest.asReadOnlyByteBuffer();
byte[] roundTripBytes = new byte[referenceBytes.length];
@@ -305,13 +362,13 @@ public class LiteralByteStringTest extends TestCase {
assertEquals(classUnderTest + " unicode must match", testString, roundTripString);
}
- public void testToString_returnsCanonicalEmptyString() throws UnsupportedEncodingException{
+ public void testToString_returnsCanonicalEmptyString() {
assertSame(classUnderTest + " must be the same string references",
ByteString.EMPTY.toString(Internal.UTF_8),
new LiteralByteString(new byte[]{}).toString(Internal.UTF_8));
}
- public void testToString_raisesException() throws UnsupportedEncodingException{
+ public void testToString_raisesException() {
try {
ByteString.EMPTY.toString("invalid");
fail("Should have thrown an exception.");
diff --git a/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java b/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
index 6cff689f..3d8c9bc4 100644
--- a/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
+++ b/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
@@ -74,6 +74,16 @@ public class MapForProto2LiteTest extends TestCase {
builder.getMutableStringToInt32Field().put("3", 33);
}
+ private void copyMapValues(TestMap source, TestMap.Builder destination) {
+ destination
+ .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
+ .putAllInt32ToStringField(source.getInt32ToStringField())
+ .putAllInt32ToBytesField(source.getInt32ToBytesField())
+ .putAllInt32ToEnumField(source.getInt32ToEnumField())
+ .putAllInt32ToMessageField(source.getInt32ToMessageField())
+ .putAllStringToInt32Field(source.getStringToInt32Field());
+ }
+
private void assertMapValuesSet(TestMap message) {
assertEquals(3, message.getInt32ToInt32Field().size());
assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
@@ -330,26 +340,36 @@ public class MapForProto2LiteTest extends TestCase {
assertMapValuesCleared(message);
}
+ public void testPutAll() throws Exception {
+ TestMap.Builder sourceBuilder = TestMap.newBuilder();
+ setMapValues(sourceBuilder);
+ TestMap source = sourceBuilder.build();
+
+ TestMap.Builder destination = TestMap.newBuilder();
+ copyMapValues(source, destination);
+ assertMapValuesSet(destination.build());
+ }
+
public void testSerializeAndParse() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValues(builder);
TestMap message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
- message = TestMap.PARSER.parseFrom(message.toByteString());
+ message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesSet(message);
builder = message.toBuilder();
updateMapValues(builder);
message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
- message = TestMap.PARSER.parseFrom(message.toByteString());
+ message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesUpdated(message);
builder = message.toBuilder();
builder.clear();
message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
- message = TestMap.PARSER.parseFrom(message.toByteString());
+ message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesCleared(message);
}
diff --git a/java/src/test/java/com/google/protobuf/MapForProto2Test.java b/java/src/test/java/com/google/protobuf/MapForProto2Test.java
index 7e984040..1fa3cbdb 100644
--- a/java/src/test/java/com/google/protobuf/MapForProto2Test.java
+++ b/java/src/test/java/com/google/protobuf/MapForProto2Test.java
@@ -78,6 +78,16 @@ public class MapForProto2Test extends TestCase {
builder.getMutableStringToInt32Field().put("3", 33);
}
+ private void copyMapValues(TestMap source, TestMap.Builder destination) {
+ destination
+ .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
+ .putAllInt32ToStringField(source.getInt32ToStringField())
+ .putAllInt32ToBytesField(source.getInt32ToBytesField())
+ .putAllInt32ToEnumField(source.getInt32ToEnumField())
+ .putAllInt32ToMessageField(source.getInt32ToMessageField())
+ .putAllStringToInt32Field(source.getStringToInt32Field());
+ }
+
private void assertMapValuesSet(TestMap message) {
assertEquals(3, message.getInt32ToInt32Field().size());
assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
@@ -310,26 +320,36 @@ public class MapForProto2Test extends TestCase {
assertMapValuesCleared(message);
}
+ public void testPutAll() throws Exception {
+ TestMap.Builder sourceBuilder = TestMap.newBuilder();
+ setMapValues(sourceBuilder);
+ TestMap source = sourceBuilder.build();
+
+ TestMap.Builder destination = TestMap.newBuilder();
+ copyMapValues(source, destination);
+ assertMapValuesSet(destination.build());
+ }
+
public void testSerializeAndParse() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValues(builder);
TestMap message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
- message = TestMap.PARSER.parseFrom(message.toByteString());
+ message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesSet(message);
builder = message.toBuilder();
updateMapValues(builder);
message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
- message = TestMap.PARSER.parseFrom(message.toByteString());
+ message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesUpdated(message);
builder = message.toBuilder();
builder.clear();
message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
- message = TestMap.PARSER.parseFrom(message.toByteString());
+ message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesCleared(message);
}
diff --git a/java/src/test/java/com/google/protobuf/MapTest.java b/java/src/test/java/com/google/protobuf/MapTest.java
index 0509be15..0e5c1284 100644
--- a/java/src/test/java/com/google/protobuf/MapTest.java
+++ b/java/src/test/java/com/google/protobuf/MapTest.java
@@ -79,6 +79,16 @@ public class MapTest extends TestCase {
builder.getMutableStringToInt32Field().put("3", 33);
}
+ private void copyMapValues(TestMap source, TestMap.Builder destination) {
+ destination
+ .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
+ .putAllInt32ToStringField(source.getInt32ToStringField())
+ .putAllInt32ToBytesField(source.getInt32ToBytesField())
+ .putAllInt32ToEnumField(source.getInt32ToEnumField())
+ .putAllInt32ToMessageField(source.getInt32ToMessageField())
+ .putAllStringToInt32Field(source.getStringToInt32Field());
+ }
+
private void assertMapValuesSet(TestMap message) {
assertEquals(3, message.getInt32ToInt32Field().size());
assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
@@ -311,26 +321,52 @@ public class MapTest extends TestCase {
assertMapValuesCleared(message);
}
+ public void testPutAll() throws Exception {
+ TestMap.Builder sourceBuilder = TestMap.newBuilder();
+ setMapValues(sourceBuilder);
+ TestMap source = sourceBuilder.build();
+
+ TestMap.Builder destination = TestMap.newBuilder();
+ copyMapValues(source, destination);
+ assertMapValuesSet(destination.build());
+ }
+
+ public void testPutAllForUnknownEnumValues() throws Exception {
+ TestMap.Builder sourceBuilder = TestMap.newBuilder();
+ sourceBuilder.getMutableInt32ToEnumFieldValue().put(0, 0);
+ sourceBuilder.getMutableInt32ToEnumFieldValue().put(1, 1);
+ sourceBuilder.getMutableInt32ToEnumFieldValue().put(2, 1000); // unknown value.
+ TestMap source = sourceBuilder.build();
+
+ TestMap.Builder destinationBuilder = TestMap.newBuilder();
+ destinationBuilder.putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValue());
+ TestMap destination = destinationBuilder.build();
+
+ assertEquals(0, destination.getInt32ToEnumFieldValue().get(0).intValue());
+ assertEquals(1, destination.getInt32ToEnumFieldValue().get(1).intValue());
+ assertEquals(1000, destination.getInt32ToEnumFieldValue().get(2).intValue());
+ }
+
public void testSerializeAndParse() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValues(builder);
TestMap message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
- message = TestMap.PARSER.parseFrom(message.toByteString());
+ message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesSet(message);
builder = message.toBuilder();
updateMapValues(builder);
message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
- message = TestMap.PARSER.parseFrom(message.toByteString());
+ message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesUpdated(message);
builder = message.toBuilder();
builder.clear();
message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
- message = TestMap.PARSER.parseFrom(message.toByteString());
+ message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesCleared(message);
}
diff --git a/java/src/test/java/com/google/protobuf/ParserTest.java b/java/src/test/java/com/google/protobuf/ParserTest.java
index b11d8cb9..5a92bacf 100644
--- a/java/src/test/java/com/google/protobuf/ParserTest.java
+++ b/java/src/test/java/com/google/protobuf/ParserTest.java
@@ -58,8 +58,7 @@ import java.io.InputStream;
public class ParserTest extends TestCase {
public void testGeneratedMessageParserSingleton() throws Exception {
for (int i = 0; i < 10; i++) {
- assertEquals(TestAllTypes.PARSER,
- TestUtil.getAllSet().getParserForType());
+ assertEquals(TestAllTypes.parser(), TestUtil.getAllSet().getParserForType());
}
}
@@ -125,8 +124,7 @@ public class ParserTest extends TestCase {
public void testParsePartial() throws Exception {
- assertParsePartial(TestRequired.PARSER,
- TestRequired.newBuilder().setA(1).buildPartial());
+ assertParsePartial(TestRequired.parser(), TestRequired.newBuilder().setA(1).buildPartial());
}
private <T extends MessageLite> void assertParsePartial(
@@ -216,8 +214,8 @@ public class ParserTest extends TestCase {
public void testParseUnknownFields() throws Exception {
// All fields will be treated as unknown fields in emptyMessage.
- TestEmptyMessage emptyMessage = TestEmptyMessage.PARSER.parseFrom(
- TestUtil.getAllSet().toByteString());
+ TestEmptyMessage emptyMessage =
+ TestEmptyMessage.parser().parseFrom(TestUtil.getAllSet().toByteString());
assertEquals(
TestUtil.getAllSet().toByteString(),
emptyMessage.toByteString());
@@ -298,8 +296,7 @@ public class ParserTest extends TestCase {
// Parse TestParsingMerge.
ExtensionRegistry registry = ExtensionRegistry.newInstance();
UnittestProto.registerAllExtensions(registry);
- TestParsingMerge parsingMerge =
- TestParsingMerge.PARSER.parseFrom(data, registry);
+ TestParsingMerge parsingMerge = TestParsingMerge.parser().parseFrom(data, registry);
// Required and optional fields should be merged.
assertMessageMerged(parsingMerge.getRequiredAllTypes());
@@ -361,8 +358,7 @@ public class ParserTest extends TestCase {
// Parse TestParsingMergeLite.
ExtensionRegistry registry = ExtensionRegistry.newInstance();
UnittestLite.registerAllExtensions(registry);
- TestParsingMergeLite parsingMerge =
- TestParsingMergeLite.PARSER.parseFrom(data, registry);
+ TestParsingMergeLite parsingMerge = TestParsingMergeLite.parser().parseFrom(data, registry);
// Required and optional fields should be merged.
assertMessageMerged(parsingMerge.getRequiredAllTypes());
diff --git a/java/src/test/java/com/google/protobuf/RopeByteStringTest.java b/java/src/test/java/com/google/protobuf/RopeByteStringTest.java
index bd0d15e3..4ec3a409 100644
--- a/java/src/test/java/com/google/protobuf/RopeByteStringTest.java
+++ b/java/src/test/java/com/google/protobuf/RopeByteStringTest.java
@@ -119,7 +119,7 @@ public class RopeByteStringTest extends LiteralByteStringTest {
}
@Override
- public void testCharsetToString() throws UnsupportedEncodingException {
+ public void testCharsetToString() {
String sourceString = "I love unicode \u1234\u5678 characters";
ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
int copies = 250;
@@ -145,14 +145,15 @@ public class RopeByteStringTest extends LiteralByteStringTest {
}
@Override
- public void testToString_returnsCanonicalEmptyString() throws UnsupportedEncodingException {
+ public void testToString_returnsCanonicalEmptyString() {
RopeByteString ropeByteString =
RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY);
assertSame(classUnderTest + " must be the same string references",
ByteString.EMPTY.toString(Internal.UTF_8), ropeByteString.toString(Internal.UTF_8));
}
- public void testToString_raisesException() throws UnsupportedEncodingException{
+ @Override
+ public void testToString_raisesException() {
try {
ByteString byteString =
RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY);
@@ -172,6 +173,7 @@ public class RopeByteStringTest extends LiteralByteStringTest {
}
}
+ @Override
public void testJavaSerialization() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(out);
diff --git a/java/src/test/java/com/google/protobuf/TestUtil.java b/java/src/test/java/com/google/protobuf/TestUtil.java
index 19a96d0e..792e8665 100644
--- a/java/src/test/java/com/google/protobuf/TestUtil.java
+++ b/java/src/test/java/com/google/protobuf/TestUtil.java
@@ -732,6 +732,7 @@ public final class TestUtil {
Assert.assertEquals("424", message.getDefaultStringPiece());
Assert.assertEquals("425", message.getDefaultCord());
+ Assert.assertEquals(TestAllTypes.OneofFieldCase.ONEOF_BYTES, message.getOneofFieldCase());
Assert.assertFalse(message.hasOneofUint32());
Assert.assertFalse(message.hasOneofNestedMessage());
Assert.assertFalse(message.hasOneofString());
diff --git a/java/src/test/java/com/google/protobuf/TextFormatTest.java b/java/src/test/java/com/google/protobuf/TextFormatTest.java
index 5d846646..8294b865 100644
--- a/java/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -32,7 +32,6 @@ package com.google.protobuf;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.TextFormat.Parser.SingularOverwritePolicy;
-import protobuf_unittest.UnittestMset.TestMessageSet;
import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
import protobuf_unittest.UnittestProto.OneString;
@@ -41,6 +40,7 @@ import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
import protobuf_unittest.UnittestProto.TestEmptyMessage;
import protobuf_unittest.UnittestProto.TestOneof2;
+import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
import junit.framework.TestCase;
diff --git a/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java b/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
index 93a5ee22..8c9dcafe 100644
--- a/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
+++ b/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
@@ -461,7 +461,7 @@ public class UnknownFieldSetTest extends TestCase {
TestAllExtensions allExtensions = TestUtil.getAllExtensionsSet();
ByteString allExtensionsData = allExtensions.toByteString();
UnittestLite.TestEmptyMessageLite emptyMessageLite =
- UnittestLite.TestEmptyMessageLite.PARSER.parseFrom(allExtensionsData);
+ UnittestLite.TestEmptyMessageLite.parser().parseFrom(allExtensionsData);
ByteString data = emptyMessageLite.toByteString();
TestAllExtensions message =
TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
diff --git a/java/src/test/java/com/google/protobuf/WireFormatTest.java b/java/src/test/java/com/google/protobuf/WireFormatTest.java
index 6858524e..0175005d 100644
--- a/java/src/test/java/com/google/protobuf/WireFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/WireFormatTest.java
@@ -44,10 +44,10 @@ import protobuf_unittest.UnittestProto.TestOneof2;
import protobuf_unittest.UnittestProto.TestOneofBackwardsCompatible;
import protobuf_unittest.UnittestProto.TestPackedExtensions;
import protobuf_unittest.UnittestProto.TestPackedTypes;
-import protobuf_unittest.UnittestMset.TestMessageSet;
import protobuf_unittest.UnittestMset.RawMessageSet;
import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
+import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
diff --git a/java/src/test/java/com/google/protobuf/any_test.proto b/java/src/test/java/com/google/protobuf/any_test.proto
new file mode 100644
index 00000000..80173d8a
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/any_test.proto
@@ -0,0 +1,42 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package any_test;
+
+option java_package = "any_test";
+option java_outer_classname = "AnyTestProto";
+
+import "google/protobuf/any.proto";
+
+message TestAny {
+ google.protobuf.Any value = 1;
+}
diff --git a/java/util/pom.xml b/java/util/pom.xml
new file mode 100644
index 00000000..44a5662d
--- /dev/null
+++ b/java/util/pom.xml
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.google</groupId>
+ <artifactId>google</artifactId>
+ <version>1</version>
+ </parent>
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-java-util</artifactId>
+ <version>3.0.0-beta-1</version>
+ <packaging>bundle</packaging>
+ <name>Protocol Buffer Java API</name>
+ <description>
+ Protocol Buffers are a way of encoding structured data in an efficient yet
+ extensible format.
+ </description>
+ <inceptionYear>2008</inceptionYear>
+ <url>https://developers.google.com/protocol-buffers/</url>
+ <licenses>
+ <license>
+ <name>New BSD license</name>
+ <url>http://www.opensource.org/licenses/bsd-license.php</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+ <scm>
+ <url>https://github.com/google/protobuf</url>
+ <connection>
+ scm:git:https://github.com/google/protobuf.git
+ </connection>
+ </scm>
+ <dependencies>
+ <dependency>
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-java</artifactId>
+ <version>3.0.0-beta-1</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>18.0</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.3</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>2.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <version>2.2.1</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>**/*Test.java</include>
+ <include>../src/main/java/com/google/protobuf/TestUtil.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>generate-test-sources</id>
+ <phase>generate-test-sources</phase>
+ <configuration>
+ <tasks>
+ <mkdir dir="target/generated-test-sources" />
+ <exec executable="../../src/protoc">
+ <arg value="--java_out=target/generated-test-sources" />
+ <arg value="--proto_path=../../src" />
+ <arg value="--proto_path=src/test/java" />
+ <arg value="../../src/google/protobuf/unittest.proto" />
+ <arg value="../../src/google/protobuf/unittest_import.proto" />
+ <arg value="../../src/google/protobuf/unittest_import_public.proto" />
+ <arg value="src/test/java/com/google/protobuf/util/json_test.proto" />
+ </exec>
+ </tasks>
+ <testSourceRoot>target/generated-test-sources</testSourceRoot>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
+ <Bundle-SymbolicName>com.google.protobuf.util</Bundle-SymbolicName>
+ <Export-Package>com.google.protobuf.util;version=3.0.0-beta-1</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <profiles>
+ <profile>
+ <id>release</id>
+ <distributionManagement>
+ <snapshotRepository>
+ <id>sonatype-nexus-staging</id>
+ <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+ </snapshotRepository>
+ <repository>
+ <id>sonatype-nexus-staging</id>
+ <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+ </repository>
+ </distributionManagement>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.2.1</version>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar-no-fork</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.9.1</version>
+ <executions>
+ <execution>
+ <id>attach-javadocs</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <version>1.5</version>
+ <executions>
+ <execution>
+ <id>sign-artifacts</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>sign</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.sonatype.plugins</groupId>
+ <artifactId>nexus-staging-maven-plugin</artifactId>
+ <version>1.6.3</version>
+ <extensions>true</extensions>
+ <configuration>
+ <serverId>sonatype-nexus-staging</serverId>
+ <nexusUrl>https://oss.sonatype.org/</nexusUrl>
+ <autoReleaseAfterClose>false</autoReleaseAfterClose>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
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
new file mode 100644
index 00000000..dc2f4b84
--- /dev/null
+++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
@@ -0,0 +1,259 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.util;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.FieldMask;
+import com.google.protobuf.Message;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+import java.util.logging.Logger;
+
+/**
+ * A tree representation of a FieldMask. Each leaf node in this tree represent
+ * a field path in the FieldMask.
+ *
+ * <p>For example, FieldMask "foo.bar,foo.baz,bar.baz" as a tree will be:
+ * <pre>
+ * [root] -+- foo -+- bar
+ * | |
+ * | +- baz
+ * |
+ * +- bar --- baz
+ * </pre>
+ *
+ * <p>By representing FieldMasks with this tree structure we can easily convert
+ * a FieldMask to a canonical form, merge two FieldMasks, calculate the
+ * intersection to two FieldMasks and traverse all fields specified by the
+ * FieldMask in a message tree.
+ */
+class FieldMaskTree {
+ private static final Logger logger =
+ Logger.getLogger(FieldMaskTree.class.getName());
+
+ private static final String FIELD_PATH_SEPARATOR_REGEX = "\\.";
+
+ private static class Node {
+ public TreeMap<String, Node> children = new TreeMap<String, Node>();
+ }
+
+ private final Node root = new Node();
+
+ /** Creates an empty FieldMaskTree. */
+ public FieldMaskTree() {}
+
+ /** Creates a FieldMaskTree for a given FieldMask. */
+ public FieldMaskTree(FieldMask mask) {
+ mergeFromFieldMask(mask);
+ }
+
+ @Override
+ public String toString() {
+ return FieldMaskUtil.toString(toFieldMask());
+ }
+
+ /**
+ * Adds a field path to the tree. In a FieldMask, every field path matches the
+ * specified field as well as all its sub-fields. For example, a field path
+ * "foo.bar" matches field "foo.bar" and also "foo.bar.baz", etc. When adding
+ * a field path to the tree, redundant sub-paths will be removed. That is,
+ * after adding "foo.bar" to the tree, "foo.bar.baz" will be removed if it
+ * exists, which will turn the tree node for "foo.bar" to a leaf node.
+ * Likewise, if the field path to add is a sub-path of an existing leaf node,
+ * nothing will be changed in the tree.
+ */
+ public FieldMaskTree addFieldPath(String path) {
+ String[] parts = path.split(FIELD_PATH_SEPARATOR_REGEX);
+ if (parts.length == 0) {
+ return this;
+ }
+ Node node = root;
+ boolean createNewBranch = false;
+ // Find the matching node in the tree.
+ for (String part : parts) {
+ // Check whether the path matches an existing leaf node.
+ if (!createNewBranch && node != root && node.children.isEmpty()) {
+ // The path to add is a sub-path of an existing leaf node.
+ return this;
+ }
+ if (node.children.containsKey(part)) {
+ node = node.children.get(part);
+ } else {
+ createNewBranch = true;
+ Node tmp = new Node();
+ node.children.put(part, tmp);
+ node = tmp;
+ }
+ }
+ // Turn the matching node into a leaf node (i.e., remove sub-paths).
+ node.children.clear();
+ return this;
+ }
+
+ /**
+ * Merges all field paths in a FieldMask into this tree.
+ */
+ public FieldMaskTree mergeFromFieldMask(FieldMask mask) {
+ for (String path : mask.getPathsList()) {
+ addFieldPath(path);
+ }
+ return this;
+ }
+
+ /** Converts this tree to a FieldMask. */
+ public FieldMask toFieldMask() {
+ if (root.children.isEmpty()) {
+ return FieldMask.getDefaultInstance();
+ }
+ List<String> paths = new ArrayList<String>();
+ getFieldPaths(root, "", paths);
+ return FieldMask.newBuilder().addAllPaths(paths).build();
+ }
+
+ /** Gathers all field paths in a sub-tree. */
+ private void getFieldPaths(Node node, String path, List<String> paths) {
+ if (node.children.isEmpty()) {
+ paths.add(path);
+ return;
+ }
+ for (Entry<String, Node> entry : node.children.entrySet()) {
+ String childPath = path.isEmpty()
+ ? entry.getKey() : path + "." + entry.getKey();
+ getFieldPaths(entry.getValue(), childPath, paths);
+ }
+ }
+
+ /**
+ * Adds the intersection of this tree with the given {@code path} to
+ * {@code output}.
+ */
+ public void intersectFieldPath(String path, FieldMaskTree output) {
+ if (root.children.isEmpty()) {
+ return;
+ }
+ String[] parts = path.split(FIELD_PATH_SEPARATOR_REGEX);
+ if (parts.length == 0) {
+ return;
+ }
+ Node node = root;
+ for (String part : parts) {
+ if (node != root && node.children.isEmpty()) {
+ // The given path is a sub-path of an existing leaf node in the tree.
+ output.addFieldPath(path);
+ return;
+ }
+ if (node.children.containsKey(part)) {
+ node = node.children.get(part);
+ } else {
+ return;
+ }
+ }
+ // We found a matching node for the path. All leaf children of this matching
+ // node is in the intersection.
+ List<String> paths = new ArrayList<String>();
+ getFieldPaths(node, path, paths);
+ for (String value : paths) {
+ output.addFieldPath(value);
+ }
+ }
+
+ /**
+ * Merges all fields specified by this FieldMaskTree from {@code source} to
+ * {@code destination}.
+ */
+ public void merge(Message source, Message.Builder destination,
+ FieldMaskUtil.MergeOptions options) {
+ if (source.getDescriptorForType() != destination.getDescriptorForType()) {
+ throw new IllegalArgumentException(
+ "Cannot merge messages of different types.");
+ }
+ if (root.children.isEmpty()) {
+ return;
+ }
+ merge(root, "", source, destination, options);
+ }
+
+ /** Merges all fields specified by a sub-tree from {@code source} to
+ * {@code destination}.
+ */
+ private void merge(Node node, String path, Message source,
+ Message.Builder destination, FieldMaskUtil.MergeOptions options) {
+ assert source.getDescriptorForType() == destination.getDescriptorForType();
+
+ Descriptor descriptor = source.getDescriptorForType();
+ for (Entry<String, Node> entry : node.children.entrySet()) {
+ FieldDescriptor field =
+ descriptor.findFieldByName(entry.getKey());
+ if (field == null) {
+ logger.warning("Cannot find field \"" + entry.getKey()
+ + "\" in message type " + descriptor.getFullName());
+ continue;
+ }
+ if (!entry.getValue().children.isEmpty()) {
+ if (field.isRepeated()
+ || field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
+ logger.warning("Field \"" + field.getFullName() + "\" is not a "
+ + "singluar message field and cannot have sub-fields.");
+ continue;
+ }
+ String childPath = path.isEmpty()
+ ? entry.getKey() : path + "." + entry.getKey();
+ merge(entry.getValue(), childPath, (Message) source.getField(field),
+ destination.getFieldBuilder(field), options);
+ continue;
+ }
+ if (field.isRepeated()) {
+ if (options.replaceRepeatedFields()) {
+ destination.setField(field, source.getField(field));
+ } else {
+ for (Object element : (List) source.getField(field)) {
+ destination.addRepeatedField(field, element);
+ }
+ }
+ } else {
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ if (options.replaceMessageFields()) {
+ destination.setField(field, source.getField(field));
+ } else {
+ destination.getFieldBuilder(field).mergeFrom(
+ (Message) source.getField(field));
+ }
+ } else {
+ destination.setField(field, source.getField(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
new file mode 100644
index 00000000..7bf87858
--- /dev/null
+++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
@@ -0,0 +1,222 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.util;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.FieldMask;
+import com.google.protobuf.Internal;
+import com.google.protobuf.Message;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Utility helper functions to work with {@link com.google.protobuf.FieldMask}.
+ */
+public class FieldMaskUtil {
+ private static final String FIELD_PATH_SEPARATOR = ",";
+ private static final String FIELD_PATH_SEPARATOR_REGEX = ",";
+ private static final String FIELD_SEPARATOR_REGEX = "\\.";
+
+ private FieldMaskUtil() {}
+
+ /**
+ * Converts a FieldMask to a string.
+ */
+ public static String toString(FieldMask fieldMask) {
+ StringBuilder result = new StringBuilder();
+ boolean first = true;
+ for (String value : fieldMask.getPathsList()) {
+ if (value.isEmpty()) {
+ // Ignore empty paths.
+ continue;
+ }
+ if (first) {
+ first = false;
+ } else {
+ result.append(FIELD_PATH_SEPARATOR);
+ }
+ result.append(value);
+ }
+ return result.toString();
+ }
+
+ /**
+ * Parses from a string to a FieldMask.
+ */
+ public static FieldMask fromString(String value) {
+ return fromStringList(
+ null, Arrays.asList(value.split(FIELD_PATH_SEPARATOR_REGEX)));
+ }
+
+ /**
+ * Parses from a string to a FieldMask and validates all field paths.
+ *
+ * @throws IllegalArgumentException if any of the field path is invalid.
+ */
+ public static FieldMask fromString(Class<? extends Message> type, String value)
+ throws IllegalArgumentException {
+ return fromStringList(
+ type, Arrays.asList(value.split(FIELD_PATH_SEPARATOR_REGEX)));
+ }
+
+ /**
+ * Constructs a FieldMask for a list of field paths in a certain type.
+ *
+ * @throws IllegalArgumentException if any of the field path is not valid.
+ */
+ public static FieldMask fromStringList(
+ Class<? extends Message> type, List<String> paths)
+ throws IllegalArgumentException {
+ FieldMask.Builder builder = FieldMask.newBuilder();
+ for (String path : paths) {
+ if (path.isEmpty()) {
+ // Ignore empty field paths.
+ continue;
+ }
+ if (type != null && !isValid(type, path)) {
+ throw new IllegalArgumentException(
+ path + " is not a valid path for " + type);
+ }
+ builder.addPaths(path);
+ }
+ return builder.build();
+ }
+
+ /**
+ * Checks whether a given field path is valid.
+ */
+ public static boolean isValid(Class<? extends Message> type, String path) {
+ String[] parts = path.split(FIELD_SEPARATOR_REGEX);
+ if (parts.length == 0) {
+ return false;
+ }
+ Descriptor descriptor =
+ Internal.getDefaultInstance(type).getDescriptorForType();
+ for (String name : parts) {
+ if (descriptor == null) {
+ return false;
+ }
+ FieldDescriptor field = descriptor.findFieldByName(name);
+ if (field == null) {
+ return false;
+ }
+ if (!field.isRepeated()
+ && field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ descriptor = field.getMessageType();
+ } else {
+ descriptor = null;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Converts a FieldMask to its canonical form. In the canonical form of a
+ * FieldMask, all field paths are sorted alphabetically and redundant field
+ * paths are moved.
+ */
+ public static FieldMask normalize(FieldMask mask) {
+ return new FieldMaskTree(mask).toFieldMask();
+ }
+
+ /**
+ * Creates an union of two FieldMasks.
+ */
+ public static FieldMask union(FieldMask mask1, FieldMask mask2) {
+ return new FieldMaskTree(mask1).mergeFromFieldMask(mask2).toFieldMask();
+ }
+
+ /**
+ * Calculates the intersection of two FieldMasks.
+ */
+ public static FieldMask intersection(FieldMask mask1, FieldMask mask2) {
+ FieldMaskTree tree = new FieldMaskTree(mask1);
+ FieldMaskTree result = new FieldMaskTree();
+ for (String path : mask2.getPathsList()) {
+ tree.intersectFieldPath(path, result);
+ }
+ return result.toFieldMask();
+ }
+
+ /**
+ * Options to customize merging behavior.
+ */
+ public static class MergeOptions {
+ private boolean replaceMessageFields = false;
+ private boolean replaceRepeatedFields = false;
+
+ /**
+ * Whether to replace message fields (i.e., discard existing content in
+ * destination message fields) when merging.
+ * Default behavior is to merge the source message field into the
+ * destination message field.
+ */
+ public boolean replaceMessageFields() {
+ return replaceMessageFields;
+ }
+
+ /**
+ * Whether to replace repeated fields (i.e., discard existing content in
+ * destination repeated fields) when merging.
+ * Default behavior is to append elements from source repeated field to the
+ * destination repeated field.
+ */
+ public boolean replaceRepeatedFields() {
+ return replaceRepeatedFields;
+ }
+
+ public void setReplaceMessageFields(boolean value) {
+ replaceMessageFields = value;
+ }
+
+ public void setReplaceRepeatedFields(boolean value) {
+ replaceRepeatedFields = value;
+ }
+ }
+
+ /**
+ * Merges fields specified by a FieldMask from one message to another.
+ */
+ public static void merge(FieldMask mask, Message source,
+ Message.Builder destination, MergeOptions options) {
+ new FieldMaskTree(mask).merge(source, destination, options);
+ }
+
+ /**
+ * Merges fields specified by a FieldMask from one message to another.
+ */
+ public static void merge(FieldMask mask, Message source,
+ Message.Builder destination) {
+ merge(mask, source, destination, new MergeOptions());
+ }
+}
diff --git a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
new file mode 100644
index 00000000..c9a39153
--- /dev/null
+++ b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
@@ -0,0 +1,1571 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.util;
+
+import com.google.common.io.BaseEncoding;
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.stream.JsonReader;
+import com.google.protobuf.Any;
+import com.google.protobuf.BoolValue;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.BytesValue;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.DoubleValue;
+import com.google.protobuf.Duration;
+import com.google.protobuf.DynamicMessage;
+import com.google.protobuf.FieldMask;
+import com.google.protobuf.FloatValue;
+import com.google.protobuf.Int32Value;
+import com.google.protobuf.Int64Value;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.ListValue;
+import com.google.protobuf.Message;
+import com.google.protobuf.MessageOrBuilder;
+import com.google.protobuf.StringValue;
+import com.google.protobuf.Struct;
+import com.google.protobuf.Timestamp;
+import com.google.protobuf.UInt32Value;
+import com.google.protobuf.UInt64Value;
+import com.google.protobuf.Value;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.ParseException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Logger;
+
+/**
+ * Utility classes to convert protobuf messages to/from JSON format. The JSON
+ * format follows Proto3 JSON specification and only proto3 features are
+ * supported. Proto2 only features (e.g., extensions and unknown fields) will
+ * be discarded in the conversion. That is, when converting proto2 messages
+ * to JSON format, extensions and unknown fields will be treated as if they
+ * do not exist. This applies to proto2 messages embedded in proto3 messages
+ * as well.
+ */
+public class JsonFormat {
+ private static final Logger logger =
+ Logger.getLogger(JsonFormat.class.getName());
+
+ private JsonFormat() {}
+
+ /**
+ * Creates a {@link Printer} with default configurations.
+ */
+ public static Printer printer() {
+ return new Printer(TypeRegistry.getEmptyTypeRegistry());
+ }
+
+ /**
+ * A Printer converts protobuf message to JSON format.
+ */
+ public static class Printer {
+ private final TypeRegistry registry;
+
+ private Printer(TypeRegistry registry) {
+ this.registry = registry;
+ }
+
+ /**
+ * Creates a new {@link Printer} using the given registry. The new Printer
+ * clones all other configurations from the current {@link Printer}.
+ *
+ * @throws IllegalArgumentException if a registry is already set.
+ */
+ public Printer usingTypeRegistry(TypeRegistry registry) {
+ if (this.registry != TypeRegistry.getEmptyTypeRegistry()) {
+ throw new IllegalArgumentException("Only one registry is allowed.");
+ }
+ return new Printer(registry);
+ }
+
+ /**
+ * Converts a protobuf message to JSON format.
+ *
+ * @throws InvalidProtocolBufferException if the message contains Any types
+ * that can't be resolved.
+ * @throws IOException if writing to the output fails.
+ */
+ public void appendTo(MessageOrBuilder message, Appendable output)
+ throws IOException {
+ // TODO(xiaofeng): Investigate the allocation overhead and optimize for
+ // mobile.
+ new PrinterImpl(registry, output).print(message);
+ }
+
+ /**
+ * Converts a protobuf message to JSON format. Throws exceptions if there
+ * are unknown Any types in the message.
+ */
+ public String print(MessageOrBuilder message)
+ throws InvalidProtocolBufferException {
+ try {
+ StringBuilder builder = new StringBuilder();
+ appendTo(message, builder);
+ return builder.toString();
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ // Unexpected IOException.
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ /**
+ * Creates a {@link Parser} with default configuration.
+ */
+ public static Parser parser() {
+ return new Parser(TypeRegistry.getEmptyTypeRegistry());
+ }
+
+ /**
+ * A Parser parses JSON to protobuf message.
+ */
+ public static class Parser {
+ private final TypeRegistry registry;
+
+ private Parser(TypeRegistry registry) {
+ this.registry = registry;
+ }
+
+ /**
+ * Creates a new {@link Parser} using the given registry. The new Parser
+ * clones all other configurations from this Parser.
+ *
+ * @throws IllegalArgumentException if a registry is already set.
+ */
+ public Parser usingTypeRegistry(TypeRegistry registry) {
+ if (this.registry != TypeRegistry.getEmptyTypeRegistry()) {
+ throw new IllegalArgumentException("Only one registry is allowed.");
+ }
+ return new Parser(registry);
+ }
+
+ /**
+ * Parses from JSON into a protobuf message.
+ *
+ * @throws InvalidProtocolBufferException if the input is not valid JSON
+ * format or there are unknown fields in the input.
+ */
+ public void merge(String json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ // TODO(xiaofeng): Investigate the allocation overhead and optimize for
+ // mobile.
+ new ParserImpl(registry).merge(json, builder);
+ }
+
+ /**
+ * Parses from JSON into a protobuf message.
+ *
+ * @throws InvalidProtocolBufferException if the input is not valid JSON
+ * format or there are unknown fields in the input.
+ * @throws IOException if reading from the input throws.
+ */
+ public void merge(Reader json, Message.Builder builder)
+ throws IOException {
+ // TODO(xiaofeng): Investigate the allocation overhead and optimize for
+ // mobile.
+ new ParserImpl(registry).merge(json, builder);
+ }
+ }
+
+ /**
+ * A TypeRegistry is used to resolve Any messages in the JSON conversion.
+ * You must provide a TypeRegistry containing all message types used in
+ * Any message fields, or the JSON conversion will fail because data
+ * in Any message fields is unrecognizable. You don't need to supply a
+ * TypeRegistry if you don't use Any message fields.
+ */
+ public static class TypeRegistry {
+ private static class EmptyTypeRegistryHolder {
+ private static final TypeRegistry EMPTY = new TypeRegistry(
+ Collections.<String, Descriptor>emptyMap());
+ }
+
+ public static TypeRegistry getEmptyTypeRegistry() {
+ return EmptyTypeRegistryHolder.EMPTY;
+ }
+
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * Find a type by its full name. Returns null if it cannot be found in
+ * this {@link TypeRegistry}.
+ */
+ public Descriptor find(String name) {
+ return types.get(name);
+ }
+
+ private final Map<String, Descriptor> types;
+
+ private TypeRegistry(Map<String, Descriptor> types) {
+ this.types = types;
+ }
+
+ /**
+ * A Builder is used to build {@link TypeRegistry}.
+ */
+ public static class Builder {
+ private Builder() {}
+
+ /**
+ * Adds a message type and all types defined in the same .proto file as
+ * well as all transitively imported .proto files to this {@link Builder}.
+ */
+ public Builder add(Descriptor messageType) {
+ if (types == null) {
+ throw new IllegalStateException(
+ "A TypeRegistry.Builer can only be used once.");
+ }
+ addFile(messageType.getFile());
+ return this;
+ }
+
+ /**
+ * Adds message types and all types defined in the same .proto file as
+ * well as all transitively imported .proto files to this {@link Builder}.
+ */
+ public Builder add(Iterable<Descriptor> messageTypes) {
+ if (types == null) {
+ throw new IllegalStateException(
+ "A TypeRegistry.Builer can only be used once.");
+ }
+ for (Descriptor type : messageTypes) {
+ addFile(type.getFile());
+ }
+ return this;
+ }
+
+ /**
+ * Builds a {@link TypeRegistry}. This method can only be called once for
+ * one Builder.
+ */
+ public TypeRegistry build() {
+ TypeRegistry result = new TypeRegistry(types);
+ // Make sure the built {@link TypeRegistry} is immutable.
+ types = null;
+ return result;
+ }
+
+ private void addFile(FileDescriptor file) {
+ // Skip the file if it's already added.
+ if (files.contains(file.getName())) {
+ return;
+ }
+ for (FileDescriptor dependency : file.getDependencies()) {
+ addFile(dependency);
+ }
+ for (Descriptor message : file.getMessageTypes()) {
+ addMessage(message);
+ }
+ }
+
+ private void addMessage(Descriptor message) {
+ for (Descriptor nestedType : message.getNestedTypes()) {
+ addMessage(nestedType);
+ }
+
+ if (types.containsKey(message.getFullName())) {
+ logger.warning("Type " + message.getFullName()
+ + " is added multiple times.");
+ return;
+ }
+
+ types.put(message.getFullName(), message);
+ }
+
+ private final Set<String> files = new HashSet<String>();
+ private Map<String, Descriptor> types =
+ new HashMap<String, Descriptor>();
+ }
+ }
+
+ /**
+ * A TextGenerator adds indentation when writing formatted text.
+ */
+ private static final class TextGenerator {
+ private final Appendable output;
+ private final StringBuilder indent = new StringBuilder();
+ private boolean atStartOfLine = true;
+
+ private TextGenerator(final Appendable output) {
+ this.output = output;
+ }
+
+ /**
+ * Indent text by two spaces. After calling Indent(), two spaces will be
+ * inserted at the beginning of each line of text. Indent() may be called
+ * multiple times to produce deeper indents.
+ */
+ public void indent() {
+ indent.append(" ");
+ }
+
+ /**
+ * Reduces the current indent level by two spaces, or crashes if the indent
+ * level is zero.
+ */
+ public void outdent() {
+ final int length = indent.length();
+ if (length < 2) {
+ throw new IllegalArgumentException(
+ " Outdent() without matching Indent().");
+ }
+ indent.delete(length - 2, length);
+ }
+
+ /**
+ * Print text to the output stream.
+ */
+ public void print(final CharSequence text) throws IOException {
+ final int size = text.length();
+ int pos = 0;
+
+ for (int i = 0; i < size; i++) {
+ if (text.charAt(i) == '\n') {
+ write(text.subSequence(pos, i + 1));
+ pos = i + 1;
+ atStartOfLine = true;
+ }
+ }
+ write(text.subSequence(pos, size));
+ }
+
+ private void write(final CharSequence data) throws IOException {
+ if (data.length() == 0) {
+ return;
+ }
+ if (atStartOfLine) {
+ atStartOfLine = false;
+ output.append(indent);
+ }
+ output.append(data);
+ }
+ }
+
+ /**
+ * A Printer converts protobuf messages to JSON format.
+ */
+ private static final class PrinterImpl {
+ private final TypeRegistry registry;
+ private final TextGenerator generator;
+ // We use Gson to help handle string escapes.
+ private final Gson gson;
+
+ private static class GsonHolder {
+ private static final Gson DEFAULT_GSON = new Gson();
+ }
+
+ PrinterImpl(TypeRegistry registry, Appendable jsonOutput) {
+ this.registry = registry;
+ this.generator = new TextGenerator(jsonOutput);
+ this.gson = GsonHolder.DEFAULT_GSON;
+ }
+
+ void print(MessageOrBuilder message) throws IOException {
+ WellKnownTypePrinter specialPrinter = wellKnownTypePrinters.get(
+ message.getDescriptorForType().getFullName());
+ if (specialPrinter != null) {
+ specialPrinter.print(this, message);
+ return;
+ }
+ print(message, null);
+ }
+
+ private interface WellKnownTypePrinter {
+ void print(PrinterImpl printer, MessageOrBuilder message)
+ throws IOException;
+ }
+
+ private static final Map<String, WellKnownTypePrinter>
+ wellKnownTypePrinters = buildWellKnownTypePrinters();
+
+ private static Map<String, WellKnownTypePrinter>
+ buildWellKnownTypePrinters() {
+ Map<String, WellKnownTypePrinter> printers =
+ new HashMap<String, WellKnownTypePrinter>();
+ // Special-case Any.
+ printers.put(Any.getDescriptor().getFullName(),
+ new WellKnownTypePrinter() {
+ @Override
+ public void print(PrinterImpl printer, MessageOrBuilder message)
+ throws IOException {
+ printer.printAny(message);
+ }
+ });
+ // Special-case wrapper types.
+ WellKnownTypePrinter wrappersPrinter = new WellKnownTypePrinter() {
+ @Override
+ public void print(PrinterImpl printer, MessageOrBuilder message)
+ throws IOException {
+ printer.printWrapper(message);
+
+ }
+ };
+ printers.put(BoolValue.getDescriptor().getFullName(), wrappersPrinter);
+ printers.put(Int32Value.getDescriptor().getFullName(), wrappersPrinter);
+ printers.put(UInt32Value.getDescriptor().getFullName(), wrappersPrinter);
+ printers.put(Int64Value.getDescriptor().getFullName(), wrappersPrinter);
+ printers.put(UInt64Value.getDescriptor().getFullName(), wrappersPrinter);
+ printers.put(StringValue.getDescriptor().getFullName(), wrappersPrinter);
+ printers.put(BytesValue.getDescriptor().getFullName(), wrappersPrinter);
+ printers.put(FloatValue.getDescriptor().getFullName(), wrappersPrinter);
+ printers.put(DoubleValue.getDescriptor().getFullName(), wrappersPrinter);
+ // Special-case Timestamp.
+ printers.put(Timestamp.getDescriptor().getFullName(),
+ new WellKnownTypePrinter() {
+ @Override
+ public void print(PrinterImpl printer, MessageOrBuilder message)
+ throws IOException {
+ printer.printTimestamp(message);
+ }
+ });
+ // Special-case Duration.
+ printers.put(Duration.getDescriptor().getFullName(),
+ new WellKnownTypePrinter() {
+ @Override
+ public void print(PrinterImpl printer, MessageOrBuilder message)
+ throws IOException {
+ printer.printDuration(message);
+ }
+ });
+ // Special-case FieldMask.
+ printers.put(FieldMask.getDescriptor().getFullName(),
+ new WellKnownTypePrinter() {
+ @Override
+ public void print(PrinterImpl printer, MessageOrBuilder message)
+ throws IOException {
+ printer.printFieldMask(message);
+ }
+ });
+ // Special-case Struct.
+ printers.put(Struct.getDescriptor().getFullName(),
+ new WellKnownTypePrinter() {
+ @Override
+ public void print(PrinterImpl printer, MessageOrBuilder message)
+ throws IOException {
+ printer.printStruct(message);
+ }
+ });
+ // Special-case Value.
+ printers.put(Value.getDescriptor().getFullName(),
+ new WellKnownTypePrinter() {
+ @Override
+ public void print(PrinterImpl printer, MessageOrBuilder message)
+ throws IOException {
+ printer.printValue(message);
+ }
+ });
+ // Special-case ListValue.
+ printers.put(ListValue.getDescriptor().getFullName(),
+ new WellKnownTypePrinter() {
+ @Override
+ public void print(PrinterImpl printer, MessageOrBuilder message)
+ throws IOException {
+ printer.printListValue(message);
+ }
+ });
+ return printers;
+ }
+
+ /** Prints google.protobuf.Any */
+ private void printAny(MessageOrBuilder message) throws IOException {
+ Descriptor descriptor = message.getDescriptorForType();
+ FieldDescriptor typeUrlField = descriptor.findFieldByName("type_url");
+ FieldDescriptor valueField = descriptor.findFieldByName("value");
+ // Validates type of the message. Note that we can't just cast the message
+ // to com.google.protobuf.Any because it might be a DynamicMessage.
+ if (typeUrlField == null || valueField == null
+ || typeUrlField.getType() != FieldDescriptor.Type.STRING
+ || valueField.getType() != FieldDescriptor.Type.BYTES) {
+ throw new InvalidProtocolBufferException("Invalid Any type.");
+ }
+ String typeUrl = (String) message.getField(typeUrlField);
+ String typeName = getTypeName(typeUrl);
+ Descriptor type = registry.find(typeName);
+ if (type == null) {
+ throw new InvalidProtocolBufferException(
+ "Cannot find type for url: " + typeUrl);
+ }
+ ByteString content = (ByteString) message.getField(valueField);
+ Message contentMessage = DynamicMessage.getDefaultInstance(type)
+ .getParserForType().parseFrom(content);
+ WellKnownTypePrinter printer = wellKnownTypePrinters.get(typeName);
+ if (printer != null) {
+ // If the type is one of the well-known types, we use a special
+ // formatting.
+ generator.print("{\n");
+ generator.indent();
+ generator.print("\"@type\": " + gson.toJson(typeUrl) + ",\n");
+ generator.print("\"value\": ");
+ printer.print(this, contentMessage);
+ generator.print("\n");
+ generator.outdent();
+ generator.print("}");
+ } else {
+ // Print the content message instead (with a "@type" field added).
+ print(contentMessage, typeUrl);
+ }
+ }
+
+ /** Prints wrapper types (e.g., google.protobuf.Int32Value) */
+ private void printWrapper(MessageOrBuilder message) throws IOException {
+ Descriptor descriptor = message.getDescriptorForType();
+ FieldDescriptor valueField = descriptor.findFieldByName("value");
+ if (valueField == null) {
+ throw new InvalidProtocolBufferException("Invalid Wrapper type.");
+ }
+ // When formatting wrapper types, we just print its value field instead of
+ // the whole message.
+ printSingleFieldValue(valueField, message.getField(valueField));
+ }
+
+ private ByteString toByteString(MessageOrBuilder message) {
+ if (message instanceof Message) {
+ return ((Message) message).toByteString();
+ } else {
+ return ((Message.Builder) message).build().toByteString();
+ }
+ }
+
+ /** Prints google.protobuf.Timestamp */
+ private void printTimestamp(MessageOrBuilder message) throws IOException {
+ Timestamp value = Timestamp.parseFrom(toByteString(message));
+ generator.print("\"" + TimeUtil.toString(value) + "\"");
+ }
+
+ /** Prints google.protobuf.Duration */
+ private void printDuration(MessageOrBuilder message) throws IOException {
+ Duration value = Duration.parseFrom(toByteString(message));
+ generator.print("\"" + TimeUtil.toString(value) + "\"");
+
+ }
+
+ /** Prints google.protobuf.FieldMask */
+ private void printFieldMask(MessageOrBuilder message) throws IOException {
+ FieldMask value = FieldMask.parseFrom(toByteString(message));
+ generator.print("\"" + FieldMaskUtil.toString(value) + "\"");
+ }
+
+ /** Prints google.protobuf.Struct */
+ private void printStruct(MessageOrBuilder message) throws IOException {
+ Descriptor descriptor = message.getDescriptorForType();
+ FieldDescriptor field = descriptor.findFieldByName("fields");
+ if (field == null) {
+ throw new InvalidProtocolBufferException("Invalid Struct type.");
+ }
+ // Struct is formatted as a map object.
+ printMapFieldValue(field, message.getField(field));
+ }
+
+ /** Prints google.protobuf.Value */
+ private void printValue(MessageOrBuilder message) throws IOException {
+ // For a Value message, only the value of the field is formatted.
+ Map<FieldDescriptor, Object> fields = message.getAllFields();
+ if (fields.isEmpty()) {
+ // No value set.
+ generator.print("null");
+ return;
+ }
+ // A Value message can only have at most one field set (it only contains
+ // an oneof).
+ if (fields.size() != 1) {
+ throw new InvalidProtocolBufferException("Invalid Value type.");
+ }
+ for (Map.Entry<FieldDescriptor, Object> entry : fields.entrySet()) {
+ printSingleFieldValue(entry.getKey(), entry.getValue());
+ }
+ }
+
+ /** Prints google.protobuf.ListValue */
+ private void printListValue(MessageOrBuilder message) throws IOException {
+ Descriptor descriptor = message.getDescriptorForType();
+ FieldDescriptor field = descriptor.findFieldByName("values");
+ if (field == null) {
+ throw new InvalidProtocolBufferException("Invalid ListValue type.");
+ }
+ printRepeatedFieldValue(field, message.getField(field));
+ }
+
+ /** Prints a regular message with an optional type URL. */
+ private void print(MessageOrBuilder message, String typeUrl)
+ throws IOException {
+ generator.print("{\n");
+ generator.indent();
+
+ boolean printedField = false;
+ if (typeUrl != null) {
+ generator.print("\"@type\": " + gson.toJson(typeUrl));
+ printedField = true;
+ }
+ for (Map.Entry<FieldDescriptor, Object> field
+ : message.getAllFields().entrySet()) {
+ // Skip unknown enum fields.
+ if (field.getValue() instanceof EnumValueDescriptor
+ && ((EnumValueDescriptor) field.getValue()).getIndex() == -1) {
+ continue;
+ }
+ if (printedField) {
+ // Add line-endings for the previous field.
+ generator.print(",\n");
+ } else {
+ printedField = true;
+ }
+ printField(field.getKey(), field.getValue());
+ }
+
+ // Add line-endings for the last field.
+ if (printedField) {
+ generator.print("\n");
+ }
+ generator.outdent();
+ generator.print("}");
+ }
+
+ private void printField(FieldDescriptor field, Object value)
+ throws IOException {
+ generator.print("\"" + fieldNameToCamelName(field.getName()) + "\": ");
+ if (field.isMapField()) {
+ printMapFieldValue(field, value);
+ } else if (field.isRepeated()) {
+ printRepeatedFieldValue(field, value);
+ } else {
+ printSingleFieldValue(field, value);
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ private void printRepeatedFieldValue(FieldDescriptor field, Object value)
+ throws IOException {
+ generator.print("[");
+ boolean printedElement = false;
+ for (Object element : (List) value) {
+ // Skip unknown enum entries.
+ if (element instanceof EnumValueDescriptor
+ && ((EnumValueDescriptor) element).getIndex() == -1) {
+ continue;
+ }
+ if (printedElement) {
+ generator.print(", ");
+ } else {
+ printedElement = true;
+ }
+ printSingleFieldValue(field, element);
+ }
+ generator.print("]");
+ }
+
+ @SuppressWarnings("rawtypes")
+ private void printMapFieldValue(FieldDescriptor field, Object value)
+ throws IOException {
+ Descriptor type = field.getMessageType();
+ FieldDescriptor keyField = type.findFieldByName("key");
+ FieldDescriptor valueField = type.findFieldByName("value");
+ if (keyField == null || valueField == null) {
+ throw new InvalidProtocolBufferException("Invalid map field.");
+ }
+ generator.print("{\n");
+ generator.indent();
+ boolean printedElement = false;
+ for (Object element : (List) value) {
+ Message entry = (Message) element;
+ Object entryKey = entry.getField(keyField);
+ Object entryValue = entry.getField(valueField);
+ // Skip unknown enum entries.
+ if (entryValue instanceof EnumValueDescriptor
+ && ((EnumValueDescriptor) entryValue).getIndex() == -1) {
+ continue;
+ }
+ if (printedElement) {
+ generator.print(",\n");
+ } else {
+ printedElement = true;
+ }
+ // Key fields are always double-quoted.
+ printSingleFieldValue(keyField, entryKey, true);
+ generator.print(": ");
+ printSingleFieldValue(valueField, entryValue);
+ }
+ if (printedElement) {
+ generator.print("\n");
+ }
+ generator.outdent();
+ generator.print("}");
+ }
+
+ private void printSingleFieldValue(FieldDescriptor field, Object value)
+ throws IOException {
+ printSingleFieldValue(field, value, false);
+ }
+
+ /**
+ * Prints a field's value in JSON format.
+ *
+ * @param alwaysWithQuotes whether to always add double-quotes to primitive
+ * types.
+ */
+ private void printSingleFieldValue(
+ final FieldDescriptor field, final Object value,
+ boolean alwaysWithQuotes) throws IOException {
+ switch (field.getType()) {
+ case INT32:
+ case SINT32:
+ case SFIXED32:
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ generator.print(((Integer) value).toString());
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ break;
+
+ case INT64:
+ case SINT64:
+ case SFIXED64:
+ generator.print("\"" + ((Long) value).toString() + "\"");
+ break;
+
+ case BOOL:
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ if (((Boolean) value).booleanValue()) {
+ generator.print("true");
+ } else {
+ generator.print("false");
+ }
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ break;
+
+ case FLOAT:
+ Float floatValue = (Float) value;
+ if (floatValue.isNaN()) {
+ generator.print("\"NaN\"");
+ } else if (floatValue.isInfinite()) {
+ if (floatValue < 0) {
+ generator.print("\"-Infinity\"");
+ } else {
+ generator.print("\"Infinity\"");
+ }
+ } else {
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ generator.print(floatValue.toString());
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ }
+ break;
+
+ case DOUBLE:
+ Double doubleValue = (Double) value;
+ if (doubleValue.isNaN()) {
+ generator.print("\"NaN\"");
+ } else if (doubleValue.isInfinite()) {
+ if (doubleValue < 0) {
+ generator.print("\"-Infinity\"");
+ } else {
+ generator.print("\"Infinity\"");
+ }
+ } else {
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ generator.print(doubleValue.toString());
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ }
+ break;
+
+ case UINT32:
+ case FIXED32:
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ generator.print(unsignedToString((Integer) value));
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ break;
+
+ case UINT64:
+ case FIXED64:
+ generator.print("\"" + unsignedToString((Long) value) + "\"");
+ break;
+
+ case STRING:
+ generator.print(gson.toJson(value));
+ break;
+
+ case BYTES:
+ generator.print("\"");
+ generator.print(
+ BaseEncoding.base64().encode(((ByteString) value).toByteArray()));
+ generator.print("\"");
+ break;
+
+ case ENUM:
+ // Special-case google.protobuf.NullValue (it's an Enum).
+ if (field.getEnumType().getFullName().equals(
+ "google.protobuf.NullValue")) {
+ // No matter what value it contains, we always print it as "null".
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ generator.print("null");
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ } else {
+ generator.print(
+ "\"" + ((EnumValueDescriptor) value).getName() + "\"");
+ }
+ break;
+
+ case MESSAGE:
+ case GROUP:
+ print((Message) value);
+ break;
+ }
+ }
+ }
+
+ /** Convert an unsigned 32-bit integer to a string. */
+ private static String unsignedToString(final int value) {
+ if (value >= 0) {
+ return Integer.toString(value);
+ } else {
+ return Long.toString(value & 0x00000000FFFFFFFFL);
+ }
+ }
+
+ /** Convert an unsigned 64-bit integer to a string. */
+ private static String unsignedToString(final long value) {
+ if (value >= 0) {
+ return Long.toString(value);
+ } else {
+ // Pull off the most-significant bit so that BigInteger doesn't think
+ // the number is negative, then set it again using setBit().
+ return BigInteger.valueOf(value & Long.MAX_VALUE)
+ .setBit(Long.SIZE - 1).toString();
+ }
+ }
+
+ private static final String TYPE_URL_PREFIX = "type.googleapis.com";
+
+ private static String getTypeName(String typeUrl)
+ throws InvalidProtocolBufferException {
+ String[] parts = typeUrl.split("/");
+ if (parts.length != 2 || !parts[0].equals(TYPE_URL_PREFIX)) {
+ throw new InvalidProtocolBufferException(
+ "Invalid type url found: " + typeUrl);
+ }
+ return parts[1];
+ }
+
+ private static String fieldNameToCamelName(String name) {
+ StringBuilder result = new StringBuilder(name.length());
+ boolean isNextUpperCase = false;
+ for (int i = 0; i < name.length(); i++) {
+ Character ch = name.charAt(i);
+ if (Character.isLowerCase(ch)) {
+ if (isNextUpperCase) {
+ result.append(Character.toUpperCase(ch));
+ } else {
+ result.append(ch);
+ }
+ isNextUpperCase = false;
+ } else if (Character.isUpperCase(ch)) {
+ if (i == 0 && !isNextUpperCase) {
+ // Force first letter to lower-case unless explicitly told to
+ // capitalize it.
+ result.append(Character.toLowerCase(ch));
+ } else {
+ // Capital letters after the first are left as-is.
+ result.append(ch);
+ }
+ isNextUpperCase = false;
+ } else if (Character.isDigit(ch)) {
+ result.append(ch);
+ isNextUpperCase = true;
+ } else {
+ isNextUpperCase = true;
+ }
+ }
+ return result.toString();
+ }
+
+ private static class ParserImpl {
+ private final TypeRegistry registry;
+ private final JsonParser jsonParser;
+
+ ParserImpl(TypeRegistry registry) {
+ this.registry = registry;
+ this.jsonParser = new JsonParser();
+ }
+
+ void merge(Reader json, Message.Builder builder)
+ throws IOException {
+ JsonReader reader = new JsonReader(json);
+ reader.setLenient(false);
+ merge(jsonParser.parse(reader), builder);
+ }
+
+ void merge(String json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ try {
+ JsonReader reader = new JsonReader(new StringReader(json));
+ reader.setLenient(false);
+ merge(jsonParser.parse(reader), builder);
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (Exception e) {
+ // We convert all exceptions from JSON parsing to our own exceptions.
+ throw new InvalidProtocolBufferException(e.getMessage());
+ }
+ }
+
+ private interface WellKnownTypeParser {
+ void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException;
+ }
+
+ private static final Map<String, WellKnownTypeParser> wellKnownTypeParsers =
+ buildWellKnownTypeParsers();
+
+ private static Map<String, WellKnownTypeParser>
+ buildWellKnownTypeParsers() {
+ Map<String, WellKnownTypeParser> parsers =
+ new HashMap<String, WellKnownTypeParser>();
+ // Special-case Any.
+ parsers.put(Any.getDescriptor().getFullName(), new WellKnownTypeParser() {
+ @Override
+ public void merge(ParserImpl parser, JsonElement json,
+ Message.Builder builder) throws InvalidProtocolBufferException {
+ parser.mergeAny(json, builder);
+ }
+ });
+ // Special-case wrapper types.
+ WellKnownTypeParser wrappersPrinter = new WellKnownTypeParser() {
+ @Override
+ public void merge(ParserImpl parser, JsonElement json,
+ Message.Builder builder) throws InvalidProtocolBufferException {
+ parser.mergeWrapper(json, builder);
+ }
+ };
+ parsers.put(BoolValue.getDescriptor().getFullName(), wrappersPrinter);
+ parsers.put(Int32Value.getDescriptor().getFullName(), wrappersPrinter);
+ parsers.put(UInt32Value.getDescriptor().getFullName(), wrappersPrinter);
+ parsers.put(Int64Value.getDescriptor().getFullName(), wrappersPrinter);
+ parsers.put(UInt64Value.getDescriptor().getFullName(), wrappersPrinter);
+ parsers.put(StringValue.getDescriptor().getFullName(), wrappersPrinter);
+ parsers.put(BytesValue.getDescriptor().getFullName(), wrappersPrinter);
+ parsers.put(FloatValue.getDescriptor().getFullName(), wrappersPrinter);
+ parsers.put(DoubleValue.getDescriptor().getFullName(), wrappersPrinter);
+ // Special-case Timestamp.
+ parsers.put(Timestamp.getDescriptor().getFullName(),
+ new WellKnownTypeParser() {
+ @Override
+ public void merge(ParserImpl parser, JsonElement json,
+ Message.Builder builder) throws InvalidProtocolBufferException {
+ parser.mergeTimestamp(json, builder);
+ }
+ });
+ // Special-case Duration.
+ parsers.put(Duration.getDescriptor().getFullName(),
+ new WellKnownTypeParser() {
+ @Override
+ public void merge(ParserImpl parser, JsonElement json,
+ Message.Builder builder) throws InvalidProtocolBufferException {
+ parser.mergeDuration(json, builder);
+ }
+ });
+ // Special-case FieldMask.
+ parsers.put(FieldMask.getDescriptor().getFullName(),
+ new WellKnownTypeParser() {
+ @Override
+ public void merge(ParserImpl parser, JsonElement json,
+ Message.Builder builder) throws InvalidProtocolBufferException {
+ parser.mergeFieldMask(json, builder);
+ }
+ });
+ // Special-case Struct.
+ parsers.put(Struct.getDescriptor().getFullName(),
+ new WellKnownTypeParser() {
+ @Override
+ public void merge(ParserImpl parser, JsonElement json,
+ Message.Builder builder) throws InvalidProtocolBufferException {
+ parser.mergeStruct(json, builder);
+ }
+ });
+ // Special-case Value.
+ parsers.put(Value.getDescriptor().getFullName(),
+ new WellKnownTypeParser() {
+ @Override
+ public void merge(ParserImpl parser, JsonElement json,
+ Message.Builder builder) throws InvalidProtocolBufferException {
+ parser.mergeValue(json, builder);
+ }
+ });
+ return parsers;
+ }
+
+ private void merge(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ WellKnownTypeParser specialParser = wellKnownTypeParsers.get(
+ builder.getDescriptorForType().getFullName());
+ if (specialParser != null) {
+ specialParser.merge(this, json, builder);
+ return;
+ }
+ mergeMessage(json, builder, false);
+ }
+
+ // Maps from camel-case field names to FieldDescriptor.
+ private final Map<Descriptor, Map<String, FieldDescriptor>> fieldNameMaps =
+ new HashMap<Descriptor, Map<String, FieldDescriptor>>();
+
+ private Map<String, FieldDescriptor> getFieldNameMap(
+ Descriptor descriptor) {
+ if (!fieldNameMaps.containsKey(descriptor)) {
+ Map<String, FieldDescriptor> fieldNameMap =
+ new HashMap<String, FieldDescriptor>();
+ for (FieldDescriptor field : descriptor.getFields()) {
+ fieldNameMap.put(fieldNameToCamelName(field.getName()), field);
+ }
+ fieldNameMaps.put(descriptor, fieldNameMap);
+ return fieldNameMap;
+ }
+ return fieldNameMaps.get(descriptor);
+ }
+
+ private void mergeMessage(JsonElement json, Message.Builder builder,
+ boolean skipTypeUrl) throws InvalidProtocolBufferException {
+ if (!(json instanceof JsonObject)) {
+ throw new InvalidProtocolBufferException(
+ "Expect message object but got: " + json);
+ }
+ JsonObject object = (JsonObject) json;
+ Map<String, FieldDescriptor> fieldNameMap =
+ getFieldNameMap(builder.getDescriptorForType());
+ for (Map.Entry<String, JsonElement> entry : object.entrySet()) {
+ if (skipTypeUrl && entry.getKey().equals("@type")) {
+ continue;
+ }
+ FieldDescriptor field = fieldNameMap.get(entry.getKey());
+ if (field == null) {
+ throw new InvalidProtocolBufferException(
+ "Cannot find field: " + entry.getKey() + " in message "
+ + builder.getDescriptorForType().getFullName());
+ }
+ mergeField(field, entry.getValue(), builder);
+ }
+ }
+
+ private void mergeAny(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ Descriptor descriptor = builder.getDescriptorForType();
+ FieldDescriptor typeUrlField = descriptor.findFieldByName("type_url");
+ FieldDescriptor valueField = descriptor.findFieldByName("value");
+ // Validates type of the message. Note that we can't just cast the message
+ // to com.google.protobuf.Any because it might be a DynamicMessage.
+ if (typeUrlField == null || valueField == null
+ || typeUrlField.getType() != FieldDescriptor.Type.STRING
+ || valueField.getType() != FieldDescriptor.Type.BYTES) {
+ throw new InvalidProtocolBufferException("Invalid Any type.");
+ }
+
+ if (!(json instanceof JsonObject)) {
+ throw new InvalidProtocolBufferException(
+ "Expect message object but got: " + json);
+ }
+ JsonObject object = (JsonObject) json;
+ JsonElement typeUrlElement = object.get("@type");
+ if (typeUrlElement == null) {
+ throw new InvalidProtocolBufferException(
+ "Missing type url when parsing: " + json);
+ }
+ String typeUrl = typeUrlElement.getAsString();
+ Descriptor contentType = registry.find(getTypeName(typeUrl));
+ if (contentType == null) {
+ throw new InvalidProtocolBufferException(
+ "Cannot resolve type: " + typeUrl);
+ }
+ builder.setField(typeUrlField, typeUrl);
+ Message.Builder contentBuilder =
+ DynamicMessage.getDefaultInstance(contentType).newBuilderForType();
+ WellKnownTypeParser specialParser =
+ wellKnownTypeParsers.get(contentType.getFullName());
+ if (specialParser != null) {
+ JsonElement value = object.get("value");
+ if (value != null) {
+ specialParser.merge(this, value, contentBuilder);
+ }
+ } else {
+ mergeMessage(json, contentBuilder, true);
+ }
+ builder.setField(valueField, contentBuilder.build().toByteString());
+ }
+
+ private void mergeFieldMask(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ FieldMask value = FieldMaskUtil.fromString(json.getAsString());
+ builder.mergeFrom(value.toByteString());
+ }
+
+ private void mergeTimestamp(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ try {
+ Timestamp value = TimeUtil.parseTimestamp(json.getAsString());
+ builder.mergeFrom(value.toByteString());
+ } catch (ParseException e) {
+ throw new InvalidProtocolBufferException(
+ "Failed to parse timestamp: " + json);
+ }
+ }
+
+ private void mergeDuration(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ try {
+ Duration value = TimeUtil.parseDuration(json.getAsString());
+ builder.mergeFrom(value.toByteString());
+ } catch (ParseException e) {
+ throw new InvalidProtocolBufferException(
+ "Failed to parse duration: " + json);
+ }
+ }
+
+ private void mergeStruct(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ Descriptor descriptor = builder.getDescriptorForType();
+ FieldDescriptor field = descriptor.findFieldByName("fields");
+ if (field == null) {
+ throw new InvalidProtocolBufferException("Invalid Struct type.");
+ }
+ mergeMapField(field, json, builder);
+ }
+
+ private void mergeValue(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ Descriptor type = builder.getDescriptorForType();
+ if (json instanceof JsonPrimitive) {
+ JsonPrimitive primitive = (JsonPrimitive) json;
+ if (primitive.isBoolean()) {
+ builder.setField(type.findFieldByName("bool_value"),
+ primitive.getAsBoolean());
+ } else if (primitive.isNumber()) {
+ builder.setField(type.findFieldByName("number_value"),
+ primitive.getAsDouble());
+ } else {
+ builder.setField(type.findFieldByName("string_value"),
+ primitive.getAsString());
+ }
+ } else if (json instanceof JsonObject) {
+ FieldDescriptor field = type.findFieldByName("struct_value");
+ Message.Builder structBuilder = builder.newBuilderForField(field);
+ merge(json, structBuilder);
+ builder.setField(field, structBuilder.build());
+ } else if (json instanceof JsonArray) {
+ FieldDescriptor field = type.findFieldByName("list_value");
+ Message.Builder listBuilder = builder.newBuilderForField(field);
+ FieldDescriptor listField =
+ listBuilder.getDescriptorForType().findFieldByName("values");
+ mergeRepeatedField(listField, json, listBuilder);
+ builder.setField(field, listBuilder.build());
+ } else {
+ throw new IllegalStateException("Unexpected json data: " + json);
+ }
+ }
+
+ private void mergeWrapper(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ Descriptor type = builder.getDescriptorForType();
+ FieldDescriptor field = type.findFieldByName("value");
+ if (field == null) {
+ throw new InvalidProtocolBufferException(
+ "Invalid wrapper type: " + type.getFullName());
+ }
+ builder.setField(field, parseFieldValue(field, json, builder));
+ }
+
+ private void mergeField(FieldDescriptor field, JsonElement json,
+ Message.Builder builder) throws InvalidProtocolBufferException {
+ if (json instanceof JsonNull) {
+ // We allow "null" as value for all field types and treat it as if the
+ // field is not present.
+ return;
+ }
+ if (field.isMapField()) {
+ mergeMapField(field, json, builder);
+ } else if (field.isRepeated()) {
+ mergeRepeatedField(field, json, builder);
+ } else {
+ Object value = parseFieldValue(field, json, builder);
+ if (value != null) {
+ builder.setField(field, value);
+ }
+ }
+ }
+
+ private void mergeMapField(FieldDescriptor field, JsonElement json,
+ Message.Builder builder) throws InvalidProtocolBufferException {
+ if (!(json instanceof JsonObject)) {
+ throw new InvalidProtocolBufferException(
+ "Expect a map object but found: " + json);
+ }
+ Descriptor type = field.getMessageType();
+ FieldDescriptor keyField = type.findFieldByName("key");
+ FieldDescriptor valueField = type.findFieldByName("value");
+ if (keyField == null || valueField == null) {
+ throw new InvalidProtocolBufferException(
+ "Invalid map field: " + field.getFullName());
+ }
+ JsonObject object = (JsonObject) json;
+ for (Map.Entry<String, JsonElement> entry : object.entrySet()) {
+ Message.Builder entryBuilder = builder.newBuilderForField(field);
+ Object key = parseFieldValue(
+ keyField, new JsonPrimitive(entry.getKey()), entryBuilder);
+ Object value = parseFieldValue(
+ valueField, entry.getValue(), entryBuilder);
+ if (value == null) {
+ value = getDefaultValue(valueField, entryBuilder);
+ }
+ entryBuilder.setField(keyField, key);
+ entryBuilder.setField(valueField, value);
+ builder.addRepeatedField(field, entryBuilder.build());
+ }
+ }
+
+ /**
+ * Gets the default value for a field type. Note that we use proto3
+ * language defaults and ignore any default values set through the
+ * proto "default" option.
+ */
+ private Object getDefaultValue(FieldDescriptor field,
+ Message.Builder builder) {
+ switch (field.getType()) {
+ case INT32:
+ case SINT32:
+ case SFIXED32:
+ case UINT32:
+ case FIXED32:
+ return 0;
+ case INT64:
+ case SINT64:
+ case SFIXED64:
+ case UINT64:
+ case FIXED64:
+ return 0L;
+ case FLOAT:
+ return 0.0f;
+ case DOUBLE:
+ return 0.0;
+ case BOOL:
+ return false;
+ case STRING:
+ return "";
+ case BYTES:
+ return ByteString.EMPTY;
+ case ENUM:
+ return field.getEnumType().getValues().get(0);
+ case MESSAGE:
+ case GROUP:
+ return builder.newBuilderForField(field).getDefaultInstanceForType();
+ default:
+ throw new IllegalStateException(
+ "Invalid field type: " + field.getType());
+ }
+ }
+
+ private void mergeRepeatedField(FieldDescriptor field, JsonElement json,
+ Message.Builder builder) throws InvalidProtocolBufferException {
+ if (!(json instanceof JsonArray)) {
+ throw new InvalidProtocolBufferException(
+ "Expect an array but found: " + json);
+ }
+ JsonArray array = (JsonArray) json;
+ for (int i = 0; i < array.size(); ++i) {
+ Object value = parseFieldValue(field, array.get(i), builder);
+ if (value == null) {
+ value = getDefaultValue(field, builder);
+ }
+ builder.addRepeatedField(field, value);
+ }
+ }
+
+ private int parseInt32(JsonElement json)
+ throws InvalidProtocolBufferException {
+ try {
+ return Integer.parseInt(json.getAsString());
+ } catch (Exception e) {
+ throw new InvalidProtocolBufferException("Not an int32 value: " + json);
+ }
+ }
+
+ private long parseInt64(JsonElement json)
+ throws InvalidProtocolBufferException {
+ try {
+ return Long.parseLong(json.getAsString());
+ } catch (Exception e) {
+ throw new InvalidProtocolBufferException("Not an int64 value: " + json);
+ }
+ }
+
+ private int parseUint32(JsonElement json)
+ throws InvalidProtocolBufferException {
+ try {
+ long result = Long.parseLong(json.getAsString());
+ if (result < 0 || result > 0xFFFFFFFFL) {
+ throw new InvalidProtocolBufferException(
+ "Out of range uint32 value: " + json);
+ }
+ return (int) result;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new InvalidProtocolBufferException(
+ "Not an uint32 value: " + json);
+ }
+ }
+
+ private static final BigInteger MAX_UINT64 =
+ new BigInteger("FFFFFFFFFFFFFFFF", 16);
+
+ private long parseUint64(JsonElement json)
+ throws InvalidProtocolBufferException {
+ try {
+ BigInteger value = new BigInteger(json.getAsString());
+ if (value.compareTo(BigInteger.ZERO) < 0
+ || value.compareTo(MAX_UINT64) > 0) {
+ throw new InvalidProtocolBufferException(
+ "Out of range uint64 value: " + json);
+ }
+ return value.longValue();
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new InvalidProtocolBufferException(
+ "Not an uint64 value: " + json);
+ }
+ }
+
+ private boolean parseBool(JsonElement json)
+ throws InvalidProtocolBufferException {
+ if (json.getAsString().equals("true")) {
+ return true;
+ }
+ if (json.getAsString().equals("false")) {
+ return false;
+ }
+ throw new InvalidProtocolBufferException("Invalid bool value: " + json);
+ }
+
+ private static final double EPSILON = 1e-6;
+
+ private float parseFloat(JsonElement json)
+ throws InvalidProtocolBufferException {
+ if (json.getAsString().equals("NaN")) {
+ return Float.NaN;
+ } else if (json.getAsString().equals("Infinity")) {
+ return Float.POSITIVE_INFINITY;
+ } else if (json.getAsString().equals("-Infinity")) {
+ return Float.NEGATIVE_INFINITY;
+ }
+ try {
+ // We don't use Float.parseFloat() here because that function simply
+ // accepts all double values. Here we parse the value into a Double
+ // and do explicit range check on it.
+ double value = Double.parseDouble(json.getAsString());
+ // When a float value is printed, the printed value might be a little
+ // larger or smaller due to precision loss. Here we need to add a bit
+ // of tolerance when checking whether the float value is in range.
+ if (value > Float.MAX_VALUE * (1.0 + EPSILON)
+ || value < -Float.MAX_VALUE * (1.0 + EPSILON)) {
+ throw new InvalidProtocolBufferException(
+ "Out of range float value: " + json);
+ }
+ return (float) value;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new InvalidProtocolBufferException("Not a float value: " + json);
+ }
+ }
+
+ private static final BigDecimal MORE_THAN_ONE = new BigDecimal(
+ String.valueOf(1.0 + EPSILON));
+ // When a float value is printed, the printed value might be a little
+ // larger or smaller due to precision loss. Here we need to add a bit
+ // of tolerance when checking whether the float value is in range.
+ private static final BigDecimal MAX_DOUBLE = new BigDecimal(
+ String.valueOf(Double.MAX_VALUE)).multiply(MORE_THAN_ONE);
+ private static final BigDecimal MIN_DOUBLE = new BigDecimal(
+ String.valueOf(-Double.MAX_VALUE)).multiply(MORE_THAN_ONE);
+
+ private double parseDouble(JsonElement json)
+ throws InvalidProtocolBufferException {
+ if (json.getAsString().equals("NaN")) {
+ return Double.NaN;
+ } else if (json.getAsString().equals("Infinity")) {
+ return Double.POSITIVE_INFINITY;
+ } else if (json.getAsString().equals("-Infinity")) {
+ return Double.NEGATIVE_INFINITY;
+ }
+ try {
+ // We don't use Double.parseDouble() here because that function simply
+ // accepts all values. Here we parse the value into a BigDecimal and do
+ // explicit range check on it.
+ BigDecimal value = new BigDecimal(json.getAsString());
+ if (value.compareTo(MAX_DOUBLE) > 0
+ || value.compareTo(MIN_DOUBLE) < 0) {
+ throw new InvalidProtocolBufferException(
+ "Out of range double value: " + json);
+ }
+ return value.doubleValue();
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new InvalidProtocolBufferException(
+ "Not an double value: " + json);
+ }
+ }
+
+ private String parseString(JsonElement json) {
+ return json.getAsString();
+ }
+
+ private ByteString parseBytes(JsonElement json) {
+ return ByteString.copyFrom(
+ BaseEncoding.base64().decode(json.getAsString()));
+ }
+
+ private EnumValueDescriptor parseEnum(EnumDescriptor enumDescriptor,
+ JsonElement json) throws InvalidProtocolBufferException {
+ String value = json.getAsString();
+ EnumValueDescriptor result = enumDescriptor.findValueByName(value);
+ if (result == null) {
+ throw new InvalidProtocolBufferException(
+ "Invalid enum value: " + value + " for enum type: "
+ + enumDescriptor.getFullName());
+ }
+ return result;
+ }
+
+ private Object parseFieldValue(FieldDescriptor field, JsonElement json,
+ Message.Builder builder) throws InvalidProtocolBufferException {
+ if (json instanceof JsonNull) {
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE
+ && field.getMessageType().getFullName().equals(
+ Value.getDescriptor().getFullName())) {
+ // For every other type, "null" means absence, but for the special
+ // Value message, it means the "null_value" field has been set.
+ Value value = Value.newBuilder().setNullValueValue(0).build();
+ return builder.newBuilderForField(field).mergeFrom(
+ value.toByteString()).build();
+ }
+ return null;
+ }
+ switch (field.getType()) {
+ case INT32:
+ case SINT32:
+ case SFIXED32:
+ return parseInt32(json);
+
+ case INT64:
+ case SINT64:
+ case SFIXED64:
+ return parseInt64(json);
+
+ case BOOL:
+ return parseBool(json);
+
+ case FLOAT:
+ return parseFloat(json);
+
+ case DOUBLE:
+ return parseDouble(json);
+
+ case UINT32:
+ case FIXED32:
+ return parseUint32(json);
+
+ case UINT64:
+ case FIXED64:
+ return parseUint64(json);
+
+ case STRING:
+ return parseString(json);
+
+ case BYTES:
+ return parseBytes(json);
+
+ case ENUM:
+ return parseEnum(field.getEnumType(), json);
+
+ case MESSAGE:
+ case GROUP:
+ Message.Builder subBuilder = builder.newBuilderForField(field);
+ merge(json, subBuilder);
+ return subBuilder.build();
+
+ default:
+ throw new InvalidProtocolBufferException(
+ "Invalid field type: " + field.getType());
+ }
+ }
+ }
+}
diff --git a/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java b/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java
new file mode 100644
index 00000000..6e4b7c03
--- /dev/null
+++ b/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java
@@ -0,0 +1,545 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.util;
+
+import com.google.protobuf.Duration;
+import com.google.protobuf.Timestamp;
+
+import java.math.BigInteger;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+/**
+ * Utilities to help create/manipulate Timestamp/Duration
+ */
+public class TimeUtil {
+ // Timestamp for "0001-01-01T00:00:00Z"
+ public static final long TIMESTAMP_SECONDS_MIN = -62135596800L;
+
+ // Timestamp for "9999-12-31T23:59:59Z"
+ public static final long TIMESTAMP_SECONDS_MAX = 253402300799L;
+ public static final long DURATION_SECONDS_MIN = -315576000000L;
+ public static final long DURATION_SECONDS_MAX = 315576000000L;
+
+ private static final long NANOS_PER_SECOND = 1000000000;
+ private static final long NANOS_PER_MILLISECOND = 1000000;
+ private static final long NANOS_PER_MICROSECOND = 1000;
+ private static final long MILLIS_PER_SECOND = 1000;
+ private static final long MICROS_PER_SECOND = 1000000;
+
+ private static final SimpleDateFormat timestampFormat =
+ createTimestampFormat();
+
+ private static SimpleDateFormat createTimestampFormat() {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+ GregorianCalendar calendar =
+ new GregorianCalendar(TimeZone.getTimeZone("UTC"));
+ // We use Proleptic Gregorian Calendar (i.e., Gregorian calendar extends
+ // backwards to year one) for timestamp formating.
+ calendar.setGregorianChange(new Date(Long.MIN_VALUE));
+ sdf.setCalendar(calendar);
+ return sdf;
+ }
+
+ private TimeUtil() {}
+
+ /**
+ * Convert Timestamp to RFC 3339 date string format. The output will always
+ * be Z-normalized and uses 3, 6 or 9 fractional digits as required to
+ * represent the exact value. Note that Timestamp can only represent time
+ * from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. See
+ * https://www.ietf.org/rfc/rfc3339.txt
+ *
+ * <p>Example of generated format: "1972-01-01T10:00:20.021Z"
+ *
+ * @return The string representation of the given timestamp.
+ * @throws IllegalArgumentException if the given timestamp is not in the
+ * valid range.
+ */
+ public static String toString(Timestamp timestamp)
+ throws IllegalArgumentException {
+ StringBuilder result = new StringBuilder();
+ // Format the seconds part.
+ if (timestamp.getSeconds() < TIMESTAMP_SECONDS_MIN
+ || timestamp.getSeconds() > TIMESTAMP_SECONDS_MAX) {
+ throw new IllegalArgumentException("Timestamp is out of range.");
+ }
+ Date date = new Date(timestamp.getSeconds() * MILLIS_PER_SECOND);
+ result.append(timestampFormat.format(date));
+ // Format the nanos part.
+ if (timestamp.getNanos() < 0 || timestamp.getNanos() >= NANOS_PER_SECOND) {
+ throw new IllegalArgumentException("Timestamp has invalid nanos value.");
+ }
+ if (timestamp.getNanos() != 0) {
+ result.append(".");
+ result.append(formatNanos(timestamp.getNanos()));
+ }
+ result.append("Z");
+ return result.toString();
+ }
+
+ /**
+ * Parse from RFC 3339 date string to Timestamp. This method accepts all
+ * outputs of {@link #toString(Timestamp)} and it also accepts any fractional
+ * digits (or none) and any offset as long as they fit into nano-seconds
+ * precision.
+ *
+ * <p>Example of accepted format: "1972-01-01T10:00:20.021-05:00"
+ *
+ * @return A Timestamp parsed from the string.
+ * @throws ParseException if parsing fails.
+ */
+
+ public static Timestamp parseTimestamp(String value) throws ParseException {
+ int dayOffset = value.indexOf('T');
+ if (dayOffset == -1) {
+ throw new ParseException(
+ "Failed to parse timestamp: invalid timestamp \"" + value + "\"", 0);
+ }
+ int timezoneOffsetPosition = value.indexOf('Z', dayOffset);
+ if (timezoneOffsetPosition == -1) {
+ timezoneOffsetPosition = value.indexOf('+', dayOffset);
+ }
+ if (timezoneOffsetPosition == -1) {
+ timezoneOffsetPosition = value.indexOf('-', dayOffset);
+ }
+ if (timezoneOffsetPosition == -1) {
+ throw new ParseException(
+ "Failed to parse timestamp: missing valid timezone offset.", 0);
+ }
+ // Parse seconds and nanos.
+ String timeValue = value.substring(0, timezoneOffsetPosition);
+ String secondValue = timeValue;
+ String nanoValue = "";
+ int pointPosition = timeValue.indexOf('.');
+ if (pointPosition != -1) {
+ secondValue = timeValue.substring(0, pointPosition);
+ nanoValue = timeValue.substring(pointPosition + 1);
+ }
+ Date date = timestampFormat.parse(secondValue);
+ long seconds = date.getTime() / MILLIS_PER_SECOND;
+ int nanos = nanoValue.isEmpty() ? 0 : parseNanos(nanoValue);
+ // Parse timezone offsets.
+ if (value.charAt(timezoneOffsetPosition) == 'Z') {
+ if (value.length() != timezoneOffsetPosition + 1) {
+ throw new ParseException(
+ "Failed to parse timestamp: invalid trailing data \""
+ + value.substring(timezoneOffsetPosition) + "\"", 0);
+ }
+ } else {
+ String offsetValue = value.substring(timezoneOffsetPosition + 1);
+ long offset = parseTimezoneOffset(offsetValue);
+ if (value.charAt(timezoneOffsetPosition) == '+') {
+ seconds -= offset;
+ } else {
+ seconds += offset;
+ }
+ }
+ try {
+ return normalizedTimestamp(seconds, nanos);
+ } catch (IllegalArgumentException e) {
+ throw new ParseException(
+ "Failed to parse timestmap: timestamp is out of range.", 0);
+ }
+ }
+
+ /**
+ * Convert Duration to string format. The string format will contains 3, 6,
+ * or 9 fractional digits depending on the precision required to represent
+ * the exact Duration value. For example: "1s", "1.010s", "1.000000100s",
+ * "-3.100s" The range that can be represented by Duration is from
+ * -315,576,000,000 to +315,576,000,000 inclusive (in seconds).
+ *
+ * @return The string representation of the given duration.
+ * @throws IllegalArgumentException if the given duration is not in the valid
+ * range.
+ */
+ public static String toString(Duration duration)
+ throws IllegalArgumentException {
+ if (duration.getSeconds() < DURATION_SECONDS_MIN
+ || duration.getSeconds() > DURATION_SECONDS_MAX) {
+ throw new IllegalArgumentException("Duration is out of valid range.");
+ }
+ StringBuilder result = new StringBuilder();
+ long seconds = duration.getSeconds();
+ int nanos = duration.getNanos();
+ if (seconds < 0 || nanos < 0) {
+ if (seconds > 0 || nanos > 0) {
+ throw new IllegalArgumentException(
+ "Invalid duration: seconds value and nanos value must have the same"
+ + "sign.");
+ }
+ result.append("-");
+ seconds = -seconds;
+ nanos = -nanos;
+ }
+ result.append(seconds);
+ if (nanos != 0) {
+ result.append(".");
+ result.append(formatNanos(nanos));
+ }
+ result.append("s");
+ return result.toString();
+ }
+
+ /**
+ * Parse from a string to produce a duration.
+ *
+ * @return A Duration parsed from the string.
+ * @throws ParseException if parsing fails.
+ */
+ public static Duration parseDuration(String value) throws ParseException {
+ // Must ended with "s".
+ if (value.isEmpty() || value.charAt(value.length() - 1) != 's') {
+ throw new ParseException("Invalid duration string: " + value, 0);
+ }
+ boolean negative = false;
+ if (value.charAt(0) == '-') {
+ negative = true;
+ value = value.substring(1);
+ }
+ String secondValue = value.substring(0, value.length() - 1);
+ String nanoValue = "";
+ int pointPosition = secondValue.indexOf('.');
+ if (pointPosition != -1) {
+ nanoValue = secondValue.substring(pointPosition + 1);
+ secondValue = secondValue.substring(0, pointPosition);
+ }
+ long seconds = Long.parseLong(secondValue);
+ int nanos = nanoValue.isEmpty() ? 0 : parseNanos(nanoValue);
+ if (seconds < 0) {
+ throw new ParseException("Invalid duration string: " + value, 0);
+ }
+ if (negative) {
+ seconds = -seconds;
+ nanos = -nanos;
+ }
+ try {
+ return normalizedDuration(seconds, nanos);
+ } catch (IllegalArgumentException e) {
+ throw new ParseException("Duration value is out of range.", 0);
+ }
+ }
+
+ /**
+ * Create a Timestamp from the number of milliseconds elapsed from the epoch.
+ */
+ public static Timestamp createTimestampFromMillis(long milliseconds) {
+ return normalizedTimestamp(milliseconds / MILLIS_PER_SECOND,
+ (int) (milliseconds % MILLIS_PER_SECOND * NANOS_PER_MILLISECOND));
+ }
+
+ /**
+ * Create a Duration from the number of milliseconds.
+ */
+ public static Duration createDurationFromMillis(long milliseconds) {
+ return normalizedDuration(milliseconds / MILLIS_PER_SECOND,
+ (int) (milliseconds % MILLIS_PER_SECOND * NANOS_PER_MILLISECOND));
+ }
+
+ /**
+ * Convert a Timestamp to the number of milliseconds elapsed from the epoch.
+ *
+ * <p>The result will be rounded down to the nearest millisecond. E.g., if the
+ * timestamp represents "1969-12-31T23:59:59.999999999Z", it will be rounded
+ * to -1 millisecond.
+ */
+ public static long toMillis(Timestamp timestamp) {
+ return timestamp.getSeconds() * MILLIS_PER_SECOND + timestamp.getNanos()
+ / NANOS_PER_MILLISECOND;
+ }
+
+ /**
+ * Convert a Duration to the number of milliseconds.The result will be
+ * rounded towards 0 to the nearest millisecond. E.g., if the duration
+ * represents -1 nanosecond, it will be rounded to 0.
+ */
+ public static long toMillis(Duration duration) {
+ return duration.getSeconds() * MILLIS_PER_SECOND + duration.getNanos()
+ / NANOS_PER_MILLISECOND;
+ }
+
+ /**
+ * Create a Timestamp from the number of microseconds elapsed from the epoch.
+ */
+ public static Timestamp createTimestampFromMicros(long microseconds) {
+ return normalizedTimestamp(microseconds / MICROS_PER_SECOND,
+ (int) (microseconds % MICROS_PER_SECOND * NANOS_PER_MICROSECOND));
+ }
+
+ /**
+ * Create a Duration from the number of microseconds.
+ */
+ public static Duration createDurationFromMicros(long microseconds) {
+ return normalizedDuration(microseconds / MICROS_PER_SECOND,
+ (int) (microseconds % MICROS_PER_SECOND * NANOS_PER_MICROSECOND));
+ }
+
+ /**
+ * Convert a Timestamp to the number of microseconds elapsed from the epoch.
+ *
+ * <p>The result will be rounded down to the nearest microsecond. E.g., if the
+ * timestamp represents "1969-12-31T23:59:59.999999999Z", it will be rounded
+ * to -1 millisecond.
+ */
+ public static long toMicros(Timestamp timestamp) {
+ return timestamp.getSeconds() * MICROS_PER_SECOND + timestamp.getNanos()
+ / NANOS_PER_MICROSECOND;
+ }
+
+ /**
+ * Convert a Duration to the number of microseconds.The result will be
+ * rounded towards 0 to the nearest microseconds. E.g., if the duration
+ * represents -1 nanosecond, it will be rounded to 0.
+ */
+ public static long toMicros(Duration duration) {
+ return duration.getSeconds() * MICROS_PER_SECOND + duration.getNanos()
+ / NANOS_PER_MICROSECOND;
+ }
+
+ /**
+ * Create a Timestamp from the number of nanoseconds elapsed from the epoch.
+ */
+ public static Timestamp createTimestampFromNanos(long nanoseconds) {
+ return normalizedTimestamp(nanoseconds / NANOS_PER_SECOND,
+ (int) (nanoseconds % NANOS_PER_SECOND));
+ }
+
+ /**
+ * Create a Duration from the number of nanoseconds.
+ */
+ public static Duration createDurationFromNanos(long nanoseconds) {
+ return normalizedDuration(nanoseconds / NANOS_PER_SECOND,
+ (int) (nanoseconds % NANOS_PER_SECOND));
+ }
+
+ /**
+ * Convert a Timestamp to the number of nanoseconds elapsed from the epoch.
+ */
+ public static long toNanos(Timestamp timestamp) {
+ return timestamp.getSeconds() * NANOS_PER_SECOND + timestamp.getNanos();
+ }
+
+ /**
+ * Convert a Duration to the number of nanoseconds.
+ */
+ public static long toNanos(Duration duration) {
+ return duration.getSeconds() * NANOS_PER_SECOND + duration.getNanos();
+ }
+
+ /**
+ * Get the current time.
+ */
+ public static Timestamp getCurrentTime() {
+ return createTimestampFromMillis(System.currentTimeMillis());
+ }
+
+ /**
+ * Get the epoch.
+ */
+ public static Timestamp getEpoch() {
+ return Timestamp.getDefaultInstance();
+ }
+
+ /**
+ * Calculate the difference between two timestamps.
+ */
+ public static Duration distance(Timestamp from, Timestamp to) {
+ return normalizedDuration(to.getSeconds() - from.getSeconds(),
+ to.getNanos() - from.getNanos());
+ }
+
+ /**
+ * Add a duration to a timestamp.
+ */
+ public static Timestamp add(Timestamp start, Duration length) {
+ return normalizedTimestamp(start.getSeconds() + length.getSeconds(),
+ start.getNanos() + length.getNanos());
+ }
+
+ /**
+ * Subtract a duration from a timestamp.
+ */
+ public static Timestamp subtract(Timestamp start, Duration length) {
+ return normalizedTimestamp(start.getSeconds() - length.getSeconds(),
+ start.getNanos() - length.getNanos());
+ }
+
+ /**
+ * Add two durations.
+ */
+ public static Duration add(Duration d1, Duration d2) {
+ return normalizedDuration(d1.getSeconds() + d2.getSeconds(),
+ d1.getNanos() + d2.getNanos());
+ }
+
+ /**
+ * Subtract a duration from another.
+ */
+ public static Duration subtract(Duration d1, Duration d2) {
+ return normalizedDuration(d1.getSeconds() - d2.getSeconds(),
+ d1.getNanos() - d2.getNanos());
+ }
+
+ // Multiplications and divisions.
+
+ public static Duration multiply(Duration duration, double times) {
+ double result = duration.getSeconds() * times + duration.getNanos() * times
+ / 1000000000.0;
+ if (result < Long.MIN_VALUE || result > Long.MAX_VALUE) {
+ throw new IllegalArgumentException("Result is out of valid range.");
+ }
+ long seconds = (long) result;
+ int nanos = (int) ((result - seconds) * 1000000000);
+ return normalizedDuration(seconds, nanos);
+ }
+
+ public static Duration divide(Duration duration, double value) {
+ return multiply(duration, 1.0 / value);
+ }
+
+ public static Duration multiply(Duration duration, long times) {
+ return createDurationFromBigInteger(
+ toBigInteger(duration).multiply(toBigInteger(times)));
+ }
+
+ public static Duration divide(Duration duration, long times) {
+ return createDurationFromBigInteger(
+ toBigInteger(duration).divide(toBigInteger(times)));
+ }
+
+ public static long divide(Duration d1, Duration d2) {
+ return toBigInteger(d1).divide(toBigInteger(d2)).longValue();
+ }
+
+ public static Duration remainder(Duration d1, Duration d2) {
+ return createDurationFromBigInteger(
+ toBigInteger(d1).remainder(toBigInteger(d2)));
+ }
+
+ private static final BigInteger NANOS_PER_SECOND_BIG_INTEGER =
+ new BigInteger(String.valueOf(NANOS_PER_SECOND));
+
+ private static BigInteger toBigInteger(Duration duration) {
+ return toBigInteger(duration.getSeconds())
+ .multiply(NANOS_PER_SECOND_BIG_INTEGER)
+ .add(toBigInteger(duration.getNanos()));
+ }
+
+ private static BigInteger toBigInteger(long value) {
+ return new BigInteger(String.valueOf(value));
+ }
+
+ private static Duration createDurationFromBigInteger(BigInteger value) {
+ long seconds = value.divide(
+ new BigInteger(String.valueOf(NANOS_PER_SECOND))).longValue();
+ int nanos = value.remainder(
+ new BigInteger(String.valueOf(NANOS_PER_SECOND))).intValue();
+ return normalizedDuration(seconds, nanos);
+
+ }
+
+ private static Duration normalizedDuration(long seconds, int nanos) {
+ if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) {
+ seconds += nanos / NANOS_PER_SECOND;
+ nanos %= NANOS_PER_SECOND;
+ }
+ if (seconds > 0 && nanos < 0) {
+ nanos += NANOS_PER_SECOND;
+ seconds -= 1;
+ }
+ if (seconds < 0 && nanos > 0) {
+ nanos -= NANOS_PER_SECOND;
+ seconds += 1;
+ }
+ if (seconds < DURATION_SECONDS_MIN || seconds > DURATION_SECONDS_MAX) {
+ throw new IllegalArgumentException("Duration is out of valid range.");
+ }
+ return Duration.newBuilder().setSeconds(seconds).setNanos(nanos).build();
+ }
+
+ private static Timestamp normalizedTimestamp(long seconds, int nanos) {
+ if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) {
+ seconds += nanos / NANOS_PER_SECOND;
+ nanos %= NANOS_PER_SECOND;
+ }
+ if (nanos < 0) {
+ nanos += NANOS_PER_SECOND;
+ seconds -= 1;
+ }
+ if (seconds < TIMESTAMP_SECONDS_MIN || seconds > TIMESTAMP_SECONDS_MAX) {
+ throw new IllegalArgumentException("Timestamp is out of valid range.");
+ }
+ return Timestamp.newBuilder().setSeconds(seconds).setNanos(nanos).build();
+ }
+
+ /**
+ * Format the nano part of a timestamp or a duration.
+ */
+ private static String formatNanos(int nanos) {
+ assert nanos >= 1 && nanos <= 999999999;
+ // Determine whether to use 3, 6, or 9 digits for the nano part.
+ if (nanos % NANOS_PER_MILLISECOND == 0) {
+ return String.format("%1$03d", nanos / NANOS_PER_MILLISECOND);
+ } else if (nanos % NANOS_PER_MICROSECOND == 0) {
+ return String.format("%1$06d", nanos / NANOS_PER_MICROSECOND);
+ } else {
+ return String.format("%1$09d", nanos);
+ }
+ }
+
+ private static int parseNanos(String value) throws ParseException {
+ int result = 0;
+ for (int i = 0; i < 9; ++i) {
+ result = result * 10;
+ if (i < value.length()) {
+ if (value.charAt(i) < '0' || value.charAt(i) > '9') {
+ throw new ParseException("Invalid nanosecnds.", 0);
+ }
+ result += value.charAt(i) - '0';
+ }
+ }
+ return result;
+ }
+
+ private static long parseTimezoneOffset(String value) throws ParseException {
+ int pos = value.indexOf(':');
+ if (pos == -1) {
+ throw new ParseException("Invalid offset value: " + value, 0);
+ }
+ String hours = value.substring(0, pos);
+ String minutes = value.substring(pos + 1);
+ return (Long.parseLong(hours) * 60 + Long.parseLong(minutes)) * 60;
+ }
+}
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
new file mode 100644
index 00000000..3391f239
--- /dev/null
+++ b/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java
@@ -0,0 +1,229 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.util;
+
+import protobuf_unittest.UnittestProto.NestedTestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
+
+import junit.framework.TestCase;
+
+public class FieldMaskTreeTest extends TestCase {
+ public void testAddFieldPath() throws Exception {
+ FieldMaskTree tree = new FieldMaskTree();
+ assertEquals("", tree.toString());
+ tree.addFieldPath("");
+ assertEquals("", tree.toString());
+ // New branch.
+ tree.addFieldPath("foo");
+ assertEquals("foo", tree.toString());
+ // Redundant path.
+ tree.addFieldPath("foo");
+ assertEquals("foo", tree.toString());
+ // New branch.
+ tree.addFieldPath("bar.baz");
+ assertEquals("bar.baz,foo", tree.toString());
+ // Redundant sub-path.
+ tree.addFieldPath("foo.bar");
+ assertEquals("bar.baz,foo", tree.toString());
+ // New branch from a non-root node.
+ tree.addFieldPath("bar.quz");
+ assertEquals("bar.baz,bar.quz,foo", tree.toString());
+ // A path that matches several existing sub-paths.
+ tree.addFieldPath("bar");
+ assertEquals("bar,foo", tree.toString());
+ }
+
+ public void testMergeFromFieldMask() throws Exception {
+ FieldMaskTree tree = new FieldMaskTree(
+ FieldMaskUtil.fromString("foo,bar.baz,bar.quz"));
+ assertEquals("bar.baz,bar.quz,foo", tree.toString());
+ tree.mergeFromFieldMask(
+ FieldMaskUtil.fromString("foo.bar,bar"));
+ assertEquals("bar,foo", tree.toString());
+ }
+
+ public void testIntersectFieldPath() throws Exception {
+ FieldMaskTree tree = new FieldMaskTree(
+ FieldMaskUtil.fromString("foo,bar.baz,bar.quz"));
+ FieldMaskTree result = new FieldMaskTree();
+ // Empty path.
+ tree.intersectFieldPath("", result);
+ assertEquals("", result.toString());
+ // Non-exist path.
+ tree.intersectFieldPath("quz", result);
+ assertEquals("", result.toString());
+ // Sub-path of an existing leaf.
+ tree.intersectFieldPath("foo.bar", result);
+ assertEquals("foo.bar", result.toString());
+ // Match an existing leaf node.
+ tree.intersectFieldPath("foo", result);
+ assertEquals("foo", result.toString());
+ // Non-exist path.
+ tree.intersectFieldPath("bar.foo", result);
+ assertEquals("foo", result.toString());
+ // Match a non-leaf node.
+ tree.intersectFieldPath("bar", result);
+ assertEquals("bar.baz,bar.quz,foo", result.toString());
+ }
+
+ public void testMerge() throws Exception {
+ TestAllTypes value = TestAllTypes.newBuilder()
+ .setOptionalInt32(1234)
+ .setOptionalNestedMessage(NestedMessage.newBuilder().setBb(5678))
+ .addRepeatedInt32(4321)
+ .addRepeatedNestedMessage(NestedMessage.newBuilder().setBb(8765))
+ .build();
+ NestedTestAllTypes source = NestedTestAllTypes.newBuilder()
+ .setPayload(value)
+ .setChild(NestedTestAllTypes.newBuilder().setPayload(value))
+ .build();
+ // Now we have a message source with the following structure:
+ // [root] -+- payload -+- optional_int32
+ // | +- optional_nested_message
+ // | +- repeated_int32
+ // | +- repeated_nested_message
+ // |
+ // +- child --- payload -+- optional_int32
+ // +- optional_nested_message
+ // +- repeated_int32
+ // +- repeated_nested_message
+
+ FieldMaskUtil.MergeOptions options = new FieldMaskUtil.MergeOptions();
+
+ // Test merging each individual field.
+ NestedTestAllTypes.Builder builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree().addFieldPath("payload.optional_int32")
+ .merge(source, builder, options);
+ NestedTestAllTypes.Builder expected = NestedTestAllTypes.newBuilder();
+ expected.getPayloadBuilder().setOptionalInt32(1234);
+ assertEquals(expected.build(), builder.build());
+
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree().addFieldPath("payload.optional_nested_message")
+ .merge(source, builder, options);
+ expected = NestedTestAllTypes.newBuilder();
+ expected.getPayloadBuilder().setOptionalNestedMessage(
+ NestedMessage.newBuilder().setBb(5678));
+ assertEquals(expected.build(), builder.build());
+
+
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree().addFieldPath("payload.repeated_int32")
+ .merge(source, builder, options);
+ expected = NestedTestAllTypes.newBuilder();
+ expected.getPayloadBuilder().addRepeatedInt32(4321);
+ assertEquals(expected.build(), builder.build());
+
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree().addFieldPath("payload.repeated_nested_message")
+ .merge(source, builder, options);
+ expected = NestedTestAllTypes.newBuilder();
+ expected.getPayloadBuilder().addRepeatedNestedMessage(
+ NestedMessage.newBuilder().setBb(8765));
+ assertEquals(expected.build(), builder.build());
+
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree().addFieldPath("child.payload.optional_int32")
+ .merge(source, builder, options);
+ expected = NestedTestAllTypes.newBuilder();
+ expected.getChildBuilder().getPayloadBuilder().setOptionalInt32(1234);
+ assertEquals(expected.build(), builder.build());
+
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree().addFieldPath("child.payload.optional_nested_message")
+ .merge(source, builder, options);
+ expected = NestedTestAllTypes.newBuilder();
+ expected.getChildBuilder().getPayloadBuilder().setOptionalNestedMessage(
+ NestedMessage.newBuilder().setBb(5678));
+ assertEquals(expected.build(), builder.build());
+
+
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree().addFieldPath("child.payload.repeated_int32")
+ .merge(source, builder, options);
+ expected = NestedTestAllTypes.newBuilder();
+ expected.getChildBuilder().getPayloadBuilder().addRepeatedInt32(4321);
+ assertEquals(expected.build(), builder.build());
+
+
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree().addFieldPath("child.payload.repeated_nested_message")
+ .merge(source, builder, options);
+ expected = NestedTestAllTypes.newBuilder();
+ expected.getChildBuilder().getPayloadBuilder().addRepeatedNestedMessage(
+ NestedMessage.newBuilder().setBb(8765));
+ assertEquals(expected.build(), builder.build());
+
+ // Test merging all fields.
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree().addFieldPath("child").addFieldPath("payload")
+ .merge(source, builder, options);
+ assertEquals(source, builder.build());
+
+ // Test repeated options.
+ builder = NestedTestAllTypes.newBuilder();
+ builder.getPayloadBuilder().addRepeatedInt32(1000);
+ new FieldMaskTree().addFieldPath("payload.repeated_int32")
+ .merge(source, builder, options);
+ // Default behavior is to append repeated fields.
+ assertEquals(2, builder.getPayload().getRepeatedInt32Count());
+ assertEquals(1000, builder.getPayload().getRepeatedInt32(0));
+ assertEquals(4321, builder.getPayload().getRepeatedInt32(1));
+ // Change to replace repeated fields.
+ options.setReplaceRepeatedFields(true);
+ new FieldMaskTree().addFieldPath("payload.repeated_int32")
+ .merge(source, builder, options);
+ assertEquals(1, builder.getPayload().getRepeatedInt32Count());
+ assertEquals(4321, builder.getPayload().getRepeatedInt32(0));
+
+ // Test message options.
+ builder = NestedTestAllTypes.newBuilder();
+ builder.getPayloadBuilder().setOptionalInt32(1000);
+ builder.getPayloadBuilder().setOptionalUint32(2000);
+ new FieldMaskTree().addFieldPath("payload")
+ .merge(source, builder, options);
+ // Default behavior is to merge message fields.
+ assertEquals(1234, builder.getPayload().getOptionalInt32());
+ assertEquals(2000, builder.getPayload().getOptionalUint32());
+
+ // Change to replace message fields.
+ options.setReplaceMessageFields(true);
+ builder = NestedTestAllTypes.newBuilder();
+ builder.getPayloadBuilder().setOptionalInt32(1000);
+ builder.getPayloadBuilder().setOptionalUint32(2000);
+ new FieldMaskTree().addFieldPath("payload")
+ .merge(source, builder, options);
+ assertEquals(1234, builder.getPayload().getOptionalInt32());
+ assertEquals(0, builder.getPayload().getOptionalUint32());
+ }
+}
+
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
new file mode 100644
index 00000000..67fbe0b1
--- /dev/null
+++ b/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java
@@ -0,0 +1,135 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.util;
+
+import com.google.protobuf.FieldMask;
+import protobuf_unittest.UnittestProto.NestedTestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+
+import junit.framework.TestCase;
+
+/** Unit tests for {@link FieldMaskUtil}. */
+public class FieldMaskUtilTest extends TestCase {
+ public void testIsValid() throws Exception {
+ assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload"));
+ assertFalse(FieldMaskUtil.isValid(NestedTestAllTypes.class, "nonexist"));
+ assertTrue(FieldMaskUtil.isValid(
+ NestedTestAllTypes.class, "payload.optional_int32"));
+ assertTrue(FieldMaskUtil.isValid(
+ NestedTestAllTypes.class, "payload.repeated_int32"));
+ assertTrue(FieldMaskUtil.isValid(
+ NestedTestAllTypes.class, "payload.optional_nested_message"));
+ assertTrue(FieldMaskUtil.isValid(
+ NestedTestAllTypes.class, "payload.repeated_nested_message"));
+ assertFalse(FieldMaskUtil.isValid(
+ NestedTestAllTypes.class, "payload.nonexist"));
+
+ assertTrue(FieldMaskUtil.isValid(
+ NestedTestAllTypes.class, "payload.optional_nested_message.bb"));
+ // Repeated fields cannot have sub-paths.
+ assertFalse(FieldMaskUtil.isValid(
+ NestedTestAllTypes.class, "payload.repeated_nested_message.bb"));
+ // Non-message fields cannot have sub-paths.
+ assertFalse(FieldMaskUtil.isValid(
+ NestedTestAllTypes.class, "payload.optional_int32.bb"));
+ }
+
+ public void testToString() throws Exception {
+ assertEquals("", FieldMaskUtil.toString(FieldMask.getDefaultInstance()));
+ FieldMask mask = FieldMask.newBuilder().addPaths("foo").build();
+ assertEquals("foo", FieldMaskUtil.toString(mask));
+ mask = FieldMask.newBuilder().addPaths("foo").addPaths("bar").build();
+ assertEquals("foo,bar", FieldMaskUtil.toString(mask));
+
+ // Empty field paths are ignored.
+ mask = FieldMask.newBuilder().addPaths("").addPaths("foo").addPaths("").
+ addPaths("bar").addPaths("").build();
+ assertEquals("foo,bar", FieldMaskUtil.toString(mask));
+ }
+
+ public void testFromString() throws Exception {
+ FieldMask mask = FieldMaskUtil.fromString("");
+ assertEquals(0, mask.getPathsCount());
+ mask = FieldMaskUtil.fromString("foo");
+ assertEquals(1, mask.getPathsCount());
+ assertEquals("foo", mask.getPaths(0));
+ mask = FieldMaskUtil.fromString("foo,bar.baz");
+ assertEquals(2, mask.getPathsCount());
+ assertEquals("foo", mask.getPaths(0));
+ assertEquals("bar.baz", mask.getPaths(1));
+
+ // Empty field paths are ignore.
+ mask = FieldMaskUtil.fromString(",foo,,bar,");
+ assertEquals(2, mask.getPathsCount());
+ assertEquals("foo", mask.getPaths(0));
+ assertEquals("bar", mask.getPaths(1));
+
+ // Check whether the field paths are valid if a class parameter is provided.
+ mask = FieldMaskUtil.fromString(NestedTestAllTypes.class, ",payload");
+
+ try {
+ mask = FieldMaskUtil.fromString(
+ NestedTestAllTypes.class, "payload,nonexist");
+ fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+ }
+
+ public void testUnion() throws Exception {
+ // Only test a simple case here and expect
+ // {@link FieldMaskTreeTest#testAddFieldPath} to cover all scenarios.
+ FieldMask mask1 = FieldMaskUtil.fromString("foo,bar.baz,bar.quz");
+ FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar");
+ FieldMask result = FieldMaskUtil.union(mask1, mask2);
+ assertEquals("bar,foo", FieldMaskUtil.toString(result));
+ }
+
+ public void testIntersection() throws Exception {
+ // Only test a simple case here and expect
+ // {@link FieldMaskTreeTest#testIntersectFieldPath} to cover all scenarios.
+ FieldMask mask1 = FieldMaskUtil.fromString("foo,bar.baz,bar.quz");
+ FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar");
+ FieldMask result = FieldMaskUtil.intersection(mask1, mask2);
+ assertEquals("bar.baz,bar.quz,foo.bar", FieldMaskUtil.toString(result));
+ }
+
+ public void testMerge() throws Exception {
+ // Only test a simple case here and expect
+ // {@link FieldMaskTreeTest#testMerge} to cover all scenarios.
+ NestedTestAllTypes source = NestedTestAllTypes.newBuilder()
+ .setPayload(TestAllTypes.newBuilder().setOptionalInt32(1234))
+ .build();
+ NestedTestAllTypes.Builder builder = NestedTestAllTypes.newBuilder();
+ FieldMaskUtil.merge(FieldMaskUtil.fromString("payload"), source, builder);
+ assertEquals(1234, builder.getPayload().getOptionalInt32());
+ }
+}
diff --git a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
new file mode 100644
index 00000000..ddf5ad2a
--- /dev/null
+++ b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
@@ -0,0 +1,976 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.util;
+
+import com.google.protobuf.Any;
+import com.google.protobuf.BoolValue;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.BytesValue;
+import com.google.protobuf.DoubleValue;
+import com.google.protobuf.FloatValue;
+import com.google.protobuf.Int32Value;
+import com.google.protobuf.Int64Value;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.ListValue;
+import com.google.protobuf.Message;
+import com.google.protobuf.StringValue;
+import com.google.protobuf.Struct;
+import com.google.protobuf.UInt32Value;
+import com.google.protobuf.UInt64Value;
+import com.google.protobuf.Value;
+import com.google.protobuf.util.JsonFormat.TypeRegistry;
+import com.google.protobuf.util.JsonTestProto.TestAllTypes;
+import com.google.protobuf.util.JsonTestProto.TestAllTypes.NestedEnum;
+import com.google.protobuf.util.JsonTestProto.TestAllTypes.NestedMessage;
+import com.google.protobuf.util.JsonTestProto.TestAny;
+import com.google.protobuf.util.JsonTestProto.TestDuration;
+import com.google.protobuf.util.JsonTestProto.TestFieldMask;
+import com.google.protobuf.util.JsonTestProto.TestMap;
+import com.google.protobuf.util.JsonTestProto.TestStruct;
+import com.google.protobuf.util.JsonTestProto.TestTimestamp;
+import com.google.protobuf.util.JsonTestProto.TestWrappers;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class JsonFormatTest extends TestCase {
+ private void setAllFields(TestAllTypes.Builder builder) {
+ builder.setOptionalInt32(1234);
+ builder.setOptionalInt64(1234567890123456789L);
+ builder.setOptionalUint32(5678);
+ builder.setOptionalUint64(2345678901234567890L);
+ builder.setOptionalSint32(9012);
+ builder.setOptionalSint64(3456789012345678901L);
+ builder.setOptionalFixed32(3456);
+ builder.setOptionalFixed64(4567890123456789012L);
+ builder.setOptionalSfixed32(7890);
+ builder.setOptionalSfixed64(5678901234567890123L);
+ builder.setOptionalFloat(1.5f);
+ builder.setOptionalDouble(1.25);
+ builder.setOptionalBool(true);
+ builder.setOptionalString("Hello world!");
+ builder.setOptionalBytes(ByteString.copyFrom(new byte[]{0, 1, 2}));
+ builder.setOptionalNestedEnum(NestedEnum.BAR);
+ builder.getOptionalNestedMessageBuilder().setValue(100);
+
+ builder.addRepeatedInt32(1234);
+ builder.addRepeatedInt64(1234567890123456789L);
+ builder.addRepeatedUint32(5678);
+ builder.addRepeatedUint64(2345678901234567890L);
+ builder.addRepeatedSint32(9012);
+ builder.addRepeatedSint64(3456789012345678901L);
+ builder.addRepeatedFixed32(3456);
+ builder.addRepeatedFixed64(4567890123456789012L);
+ builder.addRepeatedSfixed32(7890);
+ builder.addRepeatedSfixed64(5678901234567890123L);
+ builder.addRepeatedFloat(1.5f);
+ builder.addRepeatedDouble(1.25);
+ builder.addRepeatedBool(true);
+ builder.addRepeatedString("Hello world!");
+ builder.addRepeatedBytes(ByteString.copyFrom(new byte[]{0, 1, 2}));
+ builder.addRepeatedNestedEnum(NestedEnum.BAR);
+ builder.addRepeatedNestedMessageBuilder().setValue(100);
+
+ builder.addRepeatedInt32(234);
+ builder.addRepeatedInt64(234567890123456789L);
+ builder.addRepeatedUint32(678);
+ builder.addRepeatedUint64(345678901234567890L);
+ builder.addRepeatedSint32(012);
+ builder.addRepeatedSint64(456789012345678901L);
+ builder.addRepeatedFixed32(456);
+ builder.addRepeatedFixed64(567890123456789012L);
+ builder.addRepeatedSfixed32(890);
+ builder.addRepeatedSfixed64(678901234567890123L);
+ builder.addRepeatedFloat(11.5f);
+ builder.addRepeatedDouble(11.25);
+ builder.addRepeatedBool(true);
+ builder.addRepeatedString("ello world!");
+ builder.addRepeatedBytes(ByteString.copyFrom(new byte[]{1, 2}));
+ builder.addRepeatedNestedEnum(NestedEnum.BAZ);
+ builder.addRepeatedNestedMessageBuilder().setValue(200);
+ }
+
+ private void assertRoundTripEquals(Message message) throws Exception {
+ assertRoundTripEquals(message, TypeRegistry.getEmptyTypeRegistry());
+ }
+
+ private void assertRoundTripEquals(Message message, TypeRegistry registry) throws Exception {
+ JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry);
+ JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(registry);
+ Message.Builder builder = message.newBuilderForType();
+ parser.merge(printer.print(message), builder);
+ Message parsedMessage = builder.build();
+ assertEquals(message.toString(), parsedMessage.toString());
+ }
+
+ private String toJsonString(Message message) throws IOException {
+ return JsonFormat.printer().print(message);
+ }
+
+ private void mergeFromJson(String json, Message.Builder builder) throws IOException {
+ JsonFormat.parser().merge(json, builder);
+ }
+
+ public void testAllFields() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ setAllFields(builder);
+ TestAllTypes message = builder.build();
+
+ assertEquals(
+ "{\n"
+ + " \"optionalInt32\": 1234,\n"
+ + " \"optionalInt64\": \"1234567890123456789\",\n"
+ + " \"optionalUint32\": 5678,\n"
+ + " \"optionalUint64\": \"2345678901234567890\",\n"
+ + " \"optionalSint32\": 9012,\n"
+ + " \"optionalSint64\": \"3456789012345678901\",\n"
+ + " \"optionalFixed32\": 3456,\n"
+ + " \"optionalFixed64\": \"4567890123456789012\",\n"
+ + " \"optionalSfixed32\": 7890,\n"
+ + " \"optionalSfixed64\": \"5678901234567890123\",\n"
+ + " \"optionalFloat\": 1.5,\n"
+ + " \"optionalDouble\": 1.25,\n"
+ + " \"optionalBool\": true,\n"
+ + " \"optionalString\": \"Hello world!\",\n"
+ + " \"optionalBytes\": \"AAEC\",\n"
+ + " \"optionalNestedMessage\": {\n"
+ + " \"value\": 100\n"
+ + " },\n"
+ + " \"optionalNestedEnum\": \"BAR\",\n"
+ + " \"repeatedInt32\": [1234, 234],\n"
+ + " \"repeatedInt64\": [\"1234567890123456789\", \"234567890123456789\"],\n"
+ + " \"repeatedUint32\": [5678, 678],\n"
+ + " \"repeatedUint64\": [\"2345678901234567890\", \"345678901234567890\"],\n"
+ + " \"repeatedSint32\": [9012, 10],\n"
+ + " \"repeatedSint64\": [\"3456789012345678901\", \"456789012345678901\"],\n"
+ + " \"repeatedFixed32\": [3456, 456],\n"
+ + " \"repeatedFixed64\": [\"4567890123456789012\", \"567890123456789012\"],\n"
+ + " \"repeatedSfixed32\": [7890, 890],\n"
+ + " \"repeatedSfixed64\": [\"5678901234567890123\", \"678901234567890123\"],\n"
+ + " \"repeatedFloat\": [1.5, 11.5],\n"
+ + " \"repeatedDouble\": [1.25, 11.25],\n"
+ + " \"repeatedBool\": [true, true],\n"
+ + " \"repeatedString\": [\"Hello world!\", \"ello world!\"],\n"
+ + " \"repeatedBytes\": [\"AAEC\", \"AQI=\"],\n"
+ + " \"repeatedNestedMessage\": [{\n"
+ + " \"value\": 100\n"
+ + " }, {\n"
+ + " \"value\": 200\n"
+ + " }],\n"
+ + " \"repeatedNestedEnum\": [\"BAR\", \"BAZ\"]\n"
+ + "}",
+ toJsonString(message));
+
+ assertRoundTripEquals(message);
+ }
+
+ public void testUnknownEnumValues() throws Exception {
+ // Unknown enum values will be dropped.
+ // TODO(xiaofeng): We may want to revisit this (whether we should omit
+ // unknown enum values).
+ TestAllTypes message = TestAllTypes.newBuilder()
+ .setOptionalNestedEnumValue(12345)
+ .addRepeatedNestedEnumValue(12345)
+ .addRepeatedNestedEnumValue(0)
+ .build();
+ assertEquals(
+ "{\n"
+ + " \"repeatedNestedEnum\": [\"FOO\"]\n"
+ + "}", toJsonString(message));
+
+ TestMap.Builder mapBuilder = TestMap.newBuilder();
+ mapBuilder.getMutableInt32ToEnumMapValue().put(1, 0);
+ mapBuilder.getMutableInt32ToEnumMapValue().put(2, 12345);
+ TestMap mapMessage = mapBuilder.build();
+ assertEquals(
+ "{\n"
+ + " \"int32ToEnumMap\": {\n"
+ + " \"1\": \"FOO\"\n"
+ + " }\n"
+ + "}", toJsonString(mapMessage));
+ }
+
+ public void testSpecialFloatValues() throws Exception {
+ TestAllTypes message = TestAllTypes.newBuilder()
+ .addRepeatedFloat(Float.NaN)
+ .addRepeatedFloat(Float.POSITIVE_INFINITY)
+ .addRepeatedFloat(Float.NEGATIVE_INFINITY)
+ .addRepeatedDouble(Double.NaN)
+ .addRepeatedDouble(Double.POSITIVE_INFINITY)
+ .addRepeatedDouble(Double.NEGATIVE_INFINITY)
+ .build();
+ assertEquals(
+ "{\n"
+ + " \"repeatedFloat\": [\"NaN\", \"Infinity\", \"-Infinity\"],\n"
+ + " \"repeatedDouble\": [\"NaN\", \"Infinity\", \"-Infinity\"]\n"
+ + "}", toJsonString(message));
+
+ assertRoundTripEquals(message);
+ }
+
+ public void testParserAcceptStringForNumbericField() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"optionalInt32\": \"1234\",\n"
+ + " \"optionalUint32\": \"5678\",\n"
+ + " \"optionalSint32\": \"9012\",\n"
+ + " \"optionalFixed32\": \"3456\",\n"
+ + " \"optionalSfixed32\": \"7890\",\n"
+ + " \"optionalFloat\": \"1.5\",\n"
+ + " \"optionalDouble\": \"1.25\",\n"
+ + " \"optionalBool\": \"true\"\n"
+ + "}", builder);
+ TestAllTypes message = builder.build();
+ assertEquals(1234, message.getOptionalInt32());
+ assertEquals(5678, message.getOptionalUint32());
+ assertEquals(9012, message.getOptionalSint32());
+ assertEquals(3456, message.getOptionalFixed32());
+ assertEquals(7890, message.getOptionalSfixed32());
+ assertEquals(1.5f, message.getOptionalFloat());
+ assertEquals(1.25, message.getOptionalDouble());
+ assertEquals(true, message.getOptionalBool());
+ }
+
+ private void assertRejects(String name, String value) {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ // Numeric form is rejected.
+ mergeFromJson("{\"" + name + "\":" + value + "}", builder);
+ fail("Exception is expected.");
+ } catch (IOException e) {
+ // Expected.
+ }
+ try {
+ // String form is also rejected.
+ mergeFromJson("{\"" + name + "\":\"" + value + "\"}", builder);
+ fail("Exception is expected.");
+ } catch (IOException e) {
+ // Expected.
+ }
+ }
+
+ private void assertAccepts(String name, String value) throws IOException {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ // Both numeric form and string form are accepted.
+ mergeFromJson("{\"" + name + "\":" + value + "}", builder);
+ mergeFromJson("{\"" + name + "\":\"" + value + "\"}", builder);
+ }
+
+ public void testParserRejectOutOfRangeNumericValues() throws Exception {
+ assertAccepts("optionalInt32", String.valueOf(Integer.MAX_VALUE));
+ assertAccepts("optionalInt32", String.valueOf(Integer.MIN_VALUE));
+ assertRejects("optionalInt32", String.valueOf(Integer.MAX_VALUE + 1L));
+ assertRejects("optionalInt32", String.valueOf(Integer.MIN_VALUE - 1L));
+
+ assertAccepts("optionalUint32", String.valueOf(Integer.MAX_VALUE + 1L));
+ assertRejects("optionalUint32", "123456789012345");
+ assertRejects("optionalUint32", "-1");
+
+ BigInteger one = new BigInteger("1");
+ BigInteger maxLong = new BigInteger(String.valueOf(Long.MAX_VALUE));
+ BigInteger minLong = new BigInteger(String.valueOf(Long.MIN_VALUE));
+ assertAccepts("optionalInt64", maxLong.toString());
+ assertAccepts("optionalInt64", minLong.toString());
+ assertRejects("optionalInt64", maxLong.add(one).toString());
+ assertRejects("optionalInt64", minLong.subtract(one).toString());
+
+ assertAccepts("optionalUint64", maxLong.add(one).toString());
+ assertRejects("optionalUint64", "1234567890123456789012345");
+ assertRejects("optionalUint64", "-1");
+
+ assertAccepts("optionalBool", "true");
+ assertRejects("optionalBool", "1");
+ assertRejects("optionalBool", "0");
+
+ assertAccepts("optionalFloat", String.valueOf(Float.MAX_VALUE));
+ assertAccepts("optionalFloat", String.valueOf(-Float.MAX_VALUE));
+ assertRejects("optionalFloat", String.valueOf(Double.MAX_VALUE));
+ assertRejects("optionalFloat", String.valueOf(-Double.MAX_VALUE));
+
+ BigDecimal moreThanOne = new BigDecimal("1.000001");
+ BigDecimal maxDouble = new BigDecimal(Double.MAX_VALUE);
+ BigDecimal minDouble = new BigDecimal(-Double.MAX_VALUE);
+ assertAccepts("optionalDouble", maxDouble.toString());
+ assertAccepts("optionalDouble", minDouble.toString());
+ assertRejects("optionalDouble", maxDouble.multiply(moreThanOne).toString());
+ assertRejects("optionalDouble", minDouble.multiply(moreThanOne).toString());
+ }
+
+ public void testParserAcceptNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"optionalInt32\": null,\n"
+ + " \"optionalInt64\": null,\n"
+ + " \"optionalUint32\": null,\n"
+ + " \"optionalUint64\": null,\n"
+ + " \"optionalSint32\": null,\n"
+ + " \"optionalSint64\": null,\n"
+ + " \"optionalFixed32\": null,\n"
+ + " \"optionalFixed64\": null,\n"
+ + " \"optionalSfixed32\": null,\n"
+ + " \"optionalSfixed64\": null,\n"
+ + " \"optionalFloat\": null,\n"
+ + " \"optionalDouble\": null,\n"
+ + " \"optionalBool\": null,\n"
+ + " \"optionalString\": null,\n"
+ + " \"optionalBytes\": null,\n"
+ + " \"optionalNestedMessage\": null,\n"
+ + " \"optionalNestedEnum\": null,\n"
+ + " \"repeatedInt32\": null,\n"
+ + " \"repeatedInt64\": null,\n"
+ + " \"repeatedUint32\": null,\n"
+ + " \"repeatedUint64\": null,\n"
+ + " \"repeatedSint32\": null,\n"
+ + " \"repeatedSint64\": null,\n"
+ + " \"repeatedFixed32\": null,\n"
+ + " \"repeatedFixed64\": null,\n"
+ + " \"repeatedSfixed32\": null,\n"
+ + " \"repeatedSfixed64\": null,\n"
+ + " \"repeatedFloat\": null,\n"
+ + " \"repeatedDouble\": null,\n"
+ + " \"repeatedBool\": null,\n"
+ + " \"repeatedString\": null,\n"
+ + " \"repeatedBytes\": null,\n"
+ + " \"repeatedNestedMessage\": null,\n"
+ + " \"repeatedNestedEnum\": null\n"
+ + "}", builder);
+ TestAllTypes message = builder.build();
+ assertEquals(TestAllTypes.getDefaultInstance(), message);
+
+ // Repeated field elements can also be null.
+ builder = TestAllTypes.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"repeatedInt32\": [null, null],\n"
+ + " \"repeatedInt64\": [null, null],\n"
+ + " \"repeatedUint32\": [null, null],\n"
+ + " \"repeatedUint64\": [null, null],\n"
+ + " \"repeatedSint32\": [null, null],\n"
+ + " \"repeatedSint64\": [null, null],\n"
+ + " \"repeatedFixed32\": [null, null],\n"
+ + " \"repeatedFixed64\": [null, null],\n"
+ + " \"repeatedSfixed32\": [null, null],\n"
+ + " \"repeatedSfixed64\": [null, null],\n"
+ + " \"repeatedFloat\": [null, null],\n"
+ + " \"repeatedDouble\": [null, null],\n"
+ + " \"repeatedBool\": [null, null],\n"
+ + " \"repeatedString\": [null, null],\n"
+ + " \"repeatedBytes\": [null, null],\n"
+ + " \"repeatedNestedMessage\": [null, null],\n"
+ + " \"repeatedNestedEnum\": [null, null]\n"
+ + "}", builder);
+ message = builder.build();
+ // "null" elements will be parsed to default values.
+ assertEquals(2, message.getRepeatedInt32Count());
+ assertEquals(0, message.getRepeatedInt32(0));
+ assertEquals(0, message.getRepeatedInt32(1));
+ assertEquals(2, message.getRepeatedInt32Count());
+ assertEquals(0, message.getRepeatedInt32(0));
+ assertEquals(0, message.getRepeatedInt32(1));
+ assertEquals(2, message.getRepeatedInt64Count());
+ assertEquals(0, message.getRepeatedInt64(0));
+ assertEquals(0, message.getRepeatedInt64(1));
+ assertEquals(2, message.getRepeatedUint32Count());
+ assertEquals(0, message.getRepeatedUint32(0));
+ assertEquals(0, message.getRepeatedUint32(1));
+ assertEquals(2, message.getRepeatedUint64Count());
+ assertEquals(0, message.getRepeatedUint64(0));
+ assertEquals(0, message.getRepeatedUint64(1));
+ assertEquals(2, message.getRepeatedSint32Count());
+ assertEquals(0, message.getRepeatedSint32(0));
+ assertEquals(0, message.getRepeatedSint32(1));
+ assertEquals(2, message.getRepeatedSint64Count());
+ assertEquals(0, message.getRepeatedSint64(0));
+ assertEquals(0, message.getRepeatedSint64(1));
+ assertEquals(2, message.getRepeatedFixed32Count());
+ assertEquals(0, message.getRepeatedFixed32(0));
+ assertEquals(0, message.getRepeatedFixed32(1));
+ assertEquals(2, message.getRepeatedFixed64Count());
+ assertEquals(0, message.getRepeatedFixed64(0));
+ assertEquals(0, message.getRepeatedFixed64(1));
+ assertEquals(2, message.getRepeatedSfixed32Count());
+ assertEquals(0, message.getRepeatedSfixed32(0));
+ assertEquals(0, message.getRepeatedSfixed32(1));
+ assertEquals(2, message.getRepeatedSfixed64Count());
+ assertEquals(0, message.getRepeatedSfixed64(0));
+ assertEquals(0, message.getRepeatedSfixed64(1));
+ assertEquals(2, message.getRepeatedFloatCount());
+ assertEquals(0f, message.getRepeatedFloat(0));
+ assertEquals(0f, message.getRepeatedFloat(1));
+ assertEquals(2, message.getRepeatedDoubleCount());
+ assertEquals(0.0, message.getRepeatedDouble(0));
+ assertEquals(0.0, message.getRepeatedDouble(1));
+ assertEquals(2, message.getRepeatedBoolCount());
+ assertFalse(message.getRepeatedBool(0));
+ assertFalse(message.getRepeatedBool(1));
+ assertEquals(2, message.getRepeatedStringCount());
+ assertTrue(message.getRepeatedString(0).isEmpty());
+ assertTrue(message.getRepeatedString(1).isEmpty());
+ assertEquals(2, message.getRepeatedBytesCount());
+ assertTrue(message.getRepeatedBytes(0).isEmpty());
+ assertTrue(message.getRepeatedBytes(1).isEmpty());
+ assertEquals(2, message.getRepeatedNestedMessageCount());
+ assertEquals(NestedMessage.getDefaultInstance(), message.getRepeatedNestedMessage(0));
+ assertEquals(NestedMessage.getDefaultInstance(), message.getRepeatedNestedMessage(1));
+ assertEquals(2, message.getRepeatedNestedEnumCount());
+ assertEquals(0, message.getRepeatedNestedEnumValue(0));
+ assertEquals(0, message.getRepeatedNestedEnumValue(1));
+ }
+
+ public void testMapFields() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ builder.getMutableInt32ToInt32Map().put(1, 10);
+ builder.getMutableInt64ToInt32Map().put(1234567890123456789L, 10);
+ builder.getMutableUint32ToInt32Map().put(2, 20);
+ builder.getMutableUint64ToInt32Map().put(2234567890123456789L, 20);
+ builder.getMutableSint32ToInt32Map().put(3, 30);
+ builder.getMutableSint64ToInt32Map().put(3234567890123456789L, 30);
+ builder.getMutableFixed32ToInt32Map().put(4, 40);
+ builder.getMutableFixed64ToInt32Map().put(4234567890123456789L, 40);
+ builder.getMutableSfixed32ToInt32Map().put(5, 50);
+ builder.getMutableSfixed64ToInt32Map().put(5234567890123456789L, 50);
+ builder.getMutableBoolToInt32Map().put(false, 6);
+ builder.getMutableStringToInt32Map().put("Hello", 10);
+
+ builder.getMutableInt32ToInt64Map().put(1, 1234567890123456789L);
+ builder.getMutableInt32ToUint32Map().put(2, 20);
+ builder.getMutableInt32ToUint64Map().put(2, 2234567890123456789L);
+ builder.getMutableInt32ToSint32Map().put(3, 30);
+ builder.getMutableInt32ToSint64Map().put(3, 3234567890123456789L);
+ builder.getMutableInt32ToFixed32Map().put(4, 40);
+ builder.getMutableInt32ToFixed64Map().put(4, 4234567890123456789L);
+ builder.getMutableInt32ToSfixed32Map().put(5, 50);
+ builder.getMutableInt32ToSfixed64Map().put(5, 5234567890123456789L);
+ builder.getMutableInt32ToFloatMap().put(6, 1.5f);
+ builder.getMutableInt32ToDoubleMap().put(6, 1.25);
+ builder.getMutableInt32ToBoolMap().put(7, false);
+ builder.getMutableInt32ToStringMap().put(7, "World");
+ builder.getMutableInt32ToBytesMap().put(
+ 8, ByteString.copyFrom(new byte[]{1, 2, 3}));
+ builder.getMutableInt32ToMessageMap().put(
+ 8, NestedMessage.newBuilder().setValue(1234).build());
+ builder.getMutableInt32ToEnumMap().put(9, NestedEnum.BAR);
+ TestMap message = builder.build();
+
+ assertEquals(
+ "{\n"
+ + " \"int32ToInt32Map\": {\n"
+ + " \"1\": 10\n"
+ + " },\n"
+ + " \"int64ToInt32Map\": {\n"
+ + " \"1234567890123456789\": 10\n"
+ + " },\n"
+ + " \"uint32ToInt32Map\": {\n"
+ + " \"2\": 20\n"
+ + " },\n"
+ + " \"uint64ToInt32Map\": {\n"
+ + " \"2234567890123456789\": 20\n"
+ + " },\n"
+ + " \"sint32ToInt32Map\": {\n"
+ + " \"3\": 30\n"
+ + " },\n"
+ + " \"sint64ToInt32Map\": {\n"
+ + " \"3234567890123456789\": 30\n"
+ + " },\n"
+ + " \"fixed32ToInt32Map\": {\n"
+ + " \"4\": 40\n"
+ + " },\n"
+ + " \"fixed64ToInt32Map\": {\n"
+ + " \"4234567890123456789\": 40\n"
+ + " },\n"
+ + " \"sfixed32ToInt32Map\": {\n"
+ + " \"5\": 50\n"
+ + " },\n"
+ + " \"sfixed64ToInt32Map\": {\n"
+ + " \"5234567890123456789\": 50\n"
+ + " },\n"
+ + " \"boolToInt32Map\": {\n"
+ + " \"false\": 6\n"
+ + " },\n"
+ + " \"stringToInt32Map\": {\n"
+ + " \"Hello\": 10\n"
+ + " },\n"
+ + " \"int32ToInt64Map\": {\n"
+ + " \"1\": \"1234567890123456789\"\n"
+ + " },\n"
+ + " \"int32ToUint32Map\": {\n"
+ + " \"2\": 20\n"
+ + " },\n"
+ + " \"int32ToUint64Map\": {\n"
+ + " \"2\": \"2234567890123456789\"\n"
+ + " },\n"
+ + " \"int32ToSint32Map\": {\n"
+ + " \"3\": 30\n"
+ + " },\n"
+ + " \"int32ToSint64Map\": {\n"
+ + " \"3\": \"3234567890123456789\"\n"
+ + " },\n"
+ + " \"int32ToFixed32Map\": {\n"
+ + " \"4\": 40\n"
+ + " },\n"
+ + " \"int32ToFixed64Map\": {\n"
+ + " \"4\": \"4234567890123456789\"\n"
+ + " },\n"
+ + " \"int32ToSfixed32Map\": {\n"
+ + " \"5\": 50\n"
+ + " },\n"
+ + " \"int32ToSfixed64Map\": {\n"
+ + " \"5\": \"5234567890123456789\"\n"
+ + " },\n"
+ + " \"int32ToFloatMap\": {\n"
+ + " \"6\": 1.5\n"
+ + " },\n"
+ + " \"int32ToDoubleMap\": {\n"
+ + " \"6\": 1.25\n"
+ + " },\n"
+ + " \"int32ToBoolMap\": {\n"
+ + " \"7\": false\n"
+ + " },\n"
+ + " \"int32ToStringMap\": {\n"
+ + " \"7\": \"World\"\n"
+ + " },\n"
+ + " \"int32ToBytesMap\": {\n"
+ + " \"8\": \"AQID\"\n"
+ + " },\n"
+ + " \"int32ToMessageMap\": {\n"
+ + " \"8\": {\n"
+ + " \"value\": 1234\n"
+ + " }\n"
+ + " },\n"
+ + " \"int32ToEnumMap\": {\n"
+ + " \"9\": \"BAR\"\n"
+ + " }\n"
+ + "}", toJsonString(message));
+ assertRoundTripEquals(message);
+
+ // Test multiple entries.
+ builder = TestMap.newBuilder();
+ builder.getMutableInt32ToInt32Map().put(1, 2);
+ builder.getMutableInt32ToInt32Map().put(3, 4);
+ message = builder.build();
+
+ assertEquals(
+ "{\n"
+ + " \"int32ToInt32Map\": {\n"
+ + " \"1\": 2,\n"
+ + " \"3\": 4\n"
+ + " }\n"
+ + "}", toJsonString(message));
+ assertRoundTripEquals(message);
+ }
+
+ public void testMapNullValueIsDefault() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"int32ToInt32Map\": {\"1\": null},\n"
+ + " \"int32ToMessageMap\": {\"2\": null}\n"
+ + "}", builder);
+ TestMap message = builder.build();
+ assertTrue(message.getInt32ToInt32Map().containsKey(1));
+ assertEquals(0, message.getInt32ToInt32Map().get(1).intValue());
+ assertTrue(message.getInt32ToMessageMap().containsKey(2));
+ assertEquals(0, message.getInt32ToMessageMap().get(2).getValue());
+ }
+
+ public void testParserAcceptNonQuotedObjectKey() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " int32ToInt32Map: {1: 2},\n"
+ + " stringToInt32Map: {hello: 3}\n"
+ + "}", builder);
+ TestMap message = builder.build();
+ assertEquals(2, message.getInt32ToInt32Map().get(1).intValue());
+ assertEquals(3, message.getStringToInt32Map().get("hello").intValue());
+ }
+
+ public void testWrappers() throws Exception {
+ TestWrappers.Builder builder = TestWrappers.newBuilder();
+ builder.getBoolValueBuilder().setValue(false);
+ builder.getInt32ValueBuilder().setValue(0);
+ builder.getInt64ValueBuilder().setValue(0);
+ builder.getUint32ValueBuilder().setValue(0);
+ builder.getUint64ValueBuilder().setValue(0);
+ builder.getFloatValueBuilder().setValue(0.0f);
+ builder.getDoubleValueBuilder().setValue(0.0);
+ builder.getStringValueBuilder().setValue("");
+ builder.getBytesValueBuilder().setValue(ByteString.EMPTY);
+ TestWrappers message = builder.build();
+
+ assertEquals(
+ "{\n"
+ + " \"int32Value\": 0,\n"
+ + " \"uint32Value\": 0,\n"
+ + " \"int64Value\": \"0\",\n"
+ + " \"uint64Value\": \"0\",\n"
+ + " \"floatValue\": 0.0,\n"
+ + " \"doubleValue\": 0.0,\n"
+ + " \"boolValue\": false,\n"
+ + " \"stringValue\": \"\",\n"
+ + " \"bytesValue\": \"\"\n"
+ + "}", toJsonString(message));
+ assertRoundTripEquals(message);
+
+ builder = TestWrappers.newBuilder();
+ builder.getBoolValueBuilder().setValue(true);
+ builder.getInt32ValueBuilder().setValue(1);
+ builder.getInt64ValueBuilder().setValue(2);
+ builder.getUint32ValueBuilder().setValue(3);
+ builder.getUint64ValueBuilder().setValue(4);
+ builder.getFloatValueBuilder().setValue(5.0f);
+ builder.getDoubleValueBuilder().setValue(6.0);
+ builder.getStringValueBuilder().setValue("7");
+ builder.getBytesValueBuilder().setValue(ByteString.copyFrom(new byte[]{8}));
+ message = builder.build();
+
+ assertEquals(
+ "{\n"
+ + " \"int32Value\": 1,\n"
+ + " \"uint32Value\": 3,\n"
+ + " \"int64Value\": \"2\",\n"
+ + " \"uint64Value\": \"4\",\n"
+ + " \"floatValue\": 5.0,\n"
+ + " \"doubleValue\": 6.0,\n"
+ + " \"boolValue\": true,\n"
+ + " \"stringValue\": \"7\",\n"
+ + " \"bytesValue\": \"CA==\"\n"
+ + "}", toJsonString(message));
+ assertRoundTripEquals(message);
+ }
+
+ public void testTimestamp() throws Exception {
+ TestTimestamp message = TestTimestamp.newBuilder()
+ .setTimestampValue(TimeUtil.parseTimestamp("1970-01-01T00:00:00Z"))
+ .build();
+
+ assertEquals(
+ "{\n"
+ + " \"timestampValue\": \"1970-01-01T00:00:00Z\"\n"
+ + "}", toJsonString(message));
+ assertRoundTripEquals(message);
+ }
+
+ public void testDuration() throws Exception {
+ TestDuration message = TestDuration.newBuilder()
+ .setDurationValue(TimeUtil.parseDuration("12345s"))
+ .build();
+
+ assertEquals(
+ "{\n"
+ + " \"durationValue\": \"12345s\"\n"
+ + "}", toJsonString(message));
+ assertRoundTripEquals(message);
+ }
+
+ public void testFieldMask() throws Exception {
+ TestFieldMask message = TestFieldMask.newBuilder()
+ .setFieldMaskValue(FieldMaskUtil.fromString("foo.bar,baz"))
+ .build();
+
+ assertEquals(
+ "{\n"
+ + " \"fieldMaskValue\": \"foo.bar,baz\"\n"
+ + "}", toJsonString(message));
+ assertRoundTripEquals(message);
+ }
+
+ public void testStruct() throws Exception {
+ // Build a struct with all possible values.
+ TestStruct.Builder builder = TestStruct.newBuilder();
+ Struct.Builder structBuilder = builder.getStructValueBuilder();
+ structBuilder.getMutableFields().put(
+ "null_value", Value.newBuilder().setNullValueValue(0).build());
+ structBuilder.getMutableFields().put(
+ "number_value", Value.newBuilder().setNumberValue(1.25).build());
+ structBuilder.getMutableFields().put(
+ "string_value", Value.newBuilder().setStringValue("hello").build());
+ Struct.Builder subStructBuilder = Struct.newBuilder();
+ subStructBuilder.getMutableFields().put(
+ "number_value", Value.newBuilder().setNumberValue(1234).build());
+ structBuilder.getMutableFields().put(
+ "struct_value", Value.newBuilder().setStructValue(subStructBuilder.build()).build());
+ ListValue.Builder listBuilder = ListValue.newBuilder();
+ listBuilder.addValues(Value.newBuilder().setNumberValue(1.125).build());
+ listBuilder.addValues(Value.newBuilder().setNullValueValue(0).build());
+ structBuilder.getMutableFields().put(
+ "list_value", Value.newBuilder().setListValue(listBuilder.build()).build());
+ TestStruct message = builder.build();
+
+ assertEquals(
+ "{\n"
+ + " \"structValue\": {\n"
+ + " \"null_value\": null,\n"
+ + " \"number_value\": 1.25,\n"
+ + " \"string_value\": \"hello\",\n"
+ + " \"struct_value\": {\n"
+ + " \"number_value\": 1234.0\n"
+ + " },\n"
+ + " \"list_value\": [1.125, null]\n"
+ + " }\n"
+ + "}", toJsonString(message));
+ assertRoundTripEquals(message);
+ }
+
+ public void testAnyFields() throws Exception {
+ TestAllTypes content = TestAllTypes.newBuilder().setOptionalInt32(1234).build();
+ TestAny message = TestAny.newBuilder().setAnyValue(Any.pack(content)).build();
+
+ // A TypeRegistry must be provided in order to convert Any types.
+ try {
+ toJsonString(message);
+ fail("Exception is expected.");
+ } catch (IOException e) {
+ // Expected.
+ }
+
+ JsonFormat.TypeRegistry registry = JsonFormat.TypeRegistry.newBuilder()
+ .add(TestAllTypes.getDescriptor()).build();
+ JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry);
+
+ assertEquals(
+ "{\n"
+ + " \"anyValue\": {\n"
+ + " \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
+ + " \"optionalInt32\": 1234\n"
+ + " }\n"
+ + "}" , printer.print(message));
+ assertRoundTripEquals(message, registry);
+
+
+ // Well-known types have a special formatting when embedded in Any.
+ //
+ // 1. Any in Any.
+ Any anyMessage = Any.pack(Any.pack(content));
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Any\",\n"
+ + " \"value\": {\n"
+ + " \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
+ + " \"optionalInt32\": 1234\n"
+ + " }\n"
+ + "}", printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+
+ // 2. Wrappers in Any.
+ anyMessage = Any.pack(Int32Value.newBuilder().setValue(12345).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Int32Value\",\n"
+ + " \"value\": 12345\n"
+ + "}", printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ anyMessage = Any.pack(UInt32Value.newBuilder().setValue(12345).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.UInt32Value\",\n"
+ + " \"value\": 12345\n"
+ + "}", printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ anyMessage = Any.pack(Int64Value.newBuilder().setValue(12345).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Int64Value\",\n"
+ + " \"value\": \"12345\"\n"
+ + "}", printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ anyMessage = Any.pack(UInt64Value.newBuilder().setValue(12345).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.UInt64Value\",\n"
+ + " \"value\": \"12345\"\n"
+ + "}", printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ anyMessage = Any.pack(FloatValue.newBuilder().setValue(12345).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.FloatValue\",\n"
+ + " \"value\": 12345.0\n"
+ + "}", printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ anyMessage = Any.pack(DoubleValue.newBuilder().setValue(12345).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.DoubleValue\",\n"
+ + " \"value\": 12345.0\n"
+ + "}", printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ anyMessage = Any.pack(BoolValue.newBuilder().setValue(true).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.BoolValue\",\n"
+ + " \"value\": true\n"
+ + "}", printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ anyMessage = Any.pack(StringValue.newBuilder().setValue("Hello").build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.StringValue\",\n"
+ + " \"value\": \"Hello\"\n"
+ + "}", printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ anyMessage = Any.pack(BytesValue.newBuilder().setValue(
+ ByteString.copyFrom(new byte[]{1, 2})).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.BytesValue\",\n"
+ + " \"value\": \"AQI=\"\n"
+ + "}", printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+
+ // 3. Timestamp in Any.
+ anyMessage = Any.pack(TimeUtil.parseTimestamp("1969-12-31T23:59:59Z"));
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Timestamp\",\n"
+ + " \"value\": \"1969-12-31T23:59:59Z\"\n"
+ + "}", printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+
+ // 4. Duration in Any
+ anyMessage = Any.pack(TimeUtil.parseDuration("12345.10s"));
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Duration\",\n"
+ + " \"value\": \"12345.100s\"\n"
+ + "}", printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+
+ // 5. FieldMask in Any
+ anyMessage = Any.pack(FieldMaskUtil.fromString("foo.bar,baz"));
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.FieldMask\",\n"
+ + " \"value\": \"foo.bar,baz\"\n"
+ + "}", printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+
+ // 6. Struct in Any
+ Struct.Builder structBuilder = Struct.newBuilder();
+ structBuilder.getMutableFields().put(
+ "number", Value.newBuilder().setNumberValue(1.125).build());
+ anyMessage = Any.pack(structBuilder.build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Struct\",\n"
+ + " \"value\": {\n"
+ + " \"number\": 1.125\n"
+ + " }\n"
+ + "}", printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ }
+
+ public void testParserMissingTypeUrl() throws Exception {
+ try {
+ Any.Builder builder = Any.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"optionalInt32\": 1234\n"
+ + "}", builder);
+ fail("Exception is expected.");
+ } catch (IOException e) {
+ // Expected.
+ }
+ }
+
+ public void testParserUnexpectedTypeUrl() throws Exception {
+ try {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
+ + " \"optionalInt32\": 12345\n"
+ + "}", builder);
+ fail("Exception is expected.");
+ } catch (IOException e) {
+ // Expected.
+ }
+ }
+
+ public void testParserRejectTrailingComma() throws Exception {
+ try {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"optionalInt32\": 12345,\n"
+ + "}", builder);
+ fail("Exception is expected.");
+ } catch (IOException e) {
+ // Expected.
+ }
+
+ // TODO(xiaofeng): GSON allows trailing comma in arrays even after I set
+ // the JsonReader to non-lenient mode. If we want to enforce strict JSON
+ // compliance, we might want to switch to a different JSON parser or
+ // implement one by ourselves.
+ // try {
+ // TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ // JsonFormat.merge(
+ // "{\n"
+ // + " \"repeatedInt32\": [12345,]\n"
+ // + "}", builder);
+ // fail("Exception is expected.");
+ // } catch (IOException e) {
+ // // Expected.
+ // }
+ }
+
+ public void testParserRejectInvalidBase64() throws Exception {
+ try {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"optionalBytes\": \"!@#$\"\n"
+ + "}", builder);
+ fail("Exception is expected.");
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testParserRejectInvalidEnumValue() throws Exception {
+ try {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"optionalNestedEnum\": \"XXX\"\n"
+ + "}", builder);
+ fail("Exception is expected.");
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+}
diff --git a/java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java b/java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java
new file mode 100644
index 00000000..fe5617e1
--- /dev/null
+++ b/java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java
@@ -0,0 +1,439 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf.util;
+
+import com.google.protobuf.Duration;
+import com.google.protobuf.Timestamp;
+
+import junit.framework.TestCase;
+
+import org.junit.Assert;
+
+import java.text.ParseException;
+
+/** Unit tests for {@link TimeUtil}. */
+public class TimeUtilTest extends TestCase {
+ public void testTimestampStringFormat() throws Exception {
+ Timestamp start = TimeUtil.parseTimestamp("0001-01-01T00:00:00Z");
+ Timestamp end = TimeUtil.parseTimestamp("9999-12-31T23:59:59.999999999Z");
+ assertEquals(TimeUtil.TIMESTAMP_SECONDS_MIN, start.getSeconds());
+ assertEquals(0, start.getNanos());
+ assertEquals(TimeUtil.TIMESTAMP_SECONDS_MAX, end.getSeconds());
+ assertEquals(999999999, end.getNanos());
+ assertEquals("0001-01-01T00:00:00Z", TimeUtil.toString(start));
+ assertEquals("9999-12-31T23:59:59.999999999Z", TimeUtil.toString(end));
+
+ Timestamp value = TimeUtil.parseTimestamp("1970-01-01T00:00:00Z");
+ assertEquals(0, value.getSeconds());
+ assertEquals(0, value.getNanos());
+
+ // Test negative timestamps.
+ value = TimeUtil.parseTimestamp("1969-12-31T23:59:59.999Z");
+ assertEquals(-1, value.getSeconds());
+ // Nano part is in the range of [0, 999999999] for Timestamp.
+ assertEquals(999000000, value.getNanos());
+
+ // Test that 3, 6, or 9 digits are used for the fractional part.
+ value = Timestamp.newBuilder().setNanos(10).build();
+ assertEquals("1970-01-01T00:00:00.000000010Z", TimeUtil.toString(value));
+ value = Timestamp.newBuilder().setNanos(10000).build();
+ assertEquals("1970-01-01T00:00:00.000010Z", TimeUtil.toString(value));
+ value = Timestamp.newBuilder().setNanos(10000000).build();
+ assertEquals("1970-01-01T00:00:00.010Z", TimeUtil.toString(value));
+
+ // Test that parsing accepts timezone offsets.
+ value = TimeUtil.parseTimestamp("1970-01-01T00:00:00.010+08:00");
+ assertEquals("1969-12-31T16:00:00.010Z", TimeUtil.toString(value));
+ value = TimeUtil.parseTimestamp("1970-01-01T00:00:00.010-08:00");
+ assertEquals("1970-01-01T08:00:00.010Z", TimeUtil.toString(value));
+ }
+
+ public void testTimetampInvalidFormat() throws Exception {
+ try {
+ // Value too small.
+ Timestamp value = Timestamp.newBuilder()
+ .setSeconds(TimeUtil.TIMESTAMP_SECONDS_MIN - 1).build();
+ TimeUtil.toString(value);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ // Value too large.
+ Timestamp value = Timestamp.newBuilder()
+ .setSeconds(TimeUtil.TIMESTAMP_SECONDS_MAX + 1).build();
+ TimeUtil.toString(value);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ // Invalid nanos value.
+ Timestamp value = Timestamp.newBuilder().setNanos(-1).build();
+ TimeUtil.toString(value);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ // Invalid nanos value.
+ Timestamp value = Timestamp.newBuilder().setNanos(1000000000).build();
+ TimeUtil.toString(value);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ // Value to small.
+ TimeUtil.parseTimestamp("0000-01-01T00:00:00Z");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Value to large.
+ TimeUtil.parseTimestamp("10000-01-01T00:00:00Z");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Missing 'T'.
+ TimeUtil.parseTimestamp("1970-01-01 00:00:00Z");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Missing 'Z'.
+ TimeUtil.parseTimestamp("1970-01-01T00:00:00");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Invalid offset.
+ TimeUtil.parseTimestamp("1970-01-01T00:00:00+0000");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Trailing text.
+ TimeUtil.parseTimestamp("1970-01-01T00:00:00Z0");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Invalid nanosecond value.
+ TimeUtil.parseTimestamp("1970-01-01T00:00:00.ABCZ");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+ }
+
+ public void testDurationStringFormat() throws Exception {
+ Timestamp start = TimeUtil.parseTimestamp("0001-01-01T00:00:00Z");
+ Timestamp end = TimeUtil.parseTimestamp("9999-12-31T23:59:59.999999999Z");
+ Duration duration = TimeUtil.distance(start, end);
+ assertEquals("315537897599.999999999s", TimeUtil.toString(duration));
+ duration = TimeUtil.distance(end, start);
+ assertEquals("-315537897599.999999999s", TimeUtil.toString(duration));
+
+ // Generated output should contain 3, 6, or 9 fractional digits.
+ duration = Duration.newBuilder().setSeconds(1).build();
+ assertEquals("1s", TimeUtil.toString(duration));
+ duration = Duration.newBuilder().setNanos(10000000).build();
+ assertEquals("0.010s", TimeUtil.toString(duration));
+ duration = Duration.newBuilder().setNanos(10000).build();
+ assertEquals("0.000010s", TimeUtil.toString(duration));
+ duration = Duration.newBuilder().setNanos(10).build();
+ assertEquals("0.000000010s", TimeUtil.toString(duration));
+
+ // Parsing accepts an fractional digits as long as they fit into nano
+ // precision.
+ duration = TimeUtil.parseDuration("0.1s");
+ assertEquals(100000000, duration.getNanos());
+ duration = TimeUtil.parseDuration("0.0001s");
+ assertEquals(100000, duration.getNanos());
+ duration = TimeUtil.parseDuration("0.0000001s");
+ assertEquals(100, duration.getNanos());
+
+ // Duration must support range from -315,576,000,000s to +315576000000s
+ // which includes negative values.
+ duration = TimeUtil.parseDuration("315576000000.999999999s");
+ assertEquals(315576000000L, duration.getSeconds());
+ assertEquals(999999999, duration.getNanos());
+ duration = TimeUtil.parseDuration("-315576000000.999999999s");
+ assertEquals(-315576000000L, duration.getSeconds());
+ assertEquals(-999999999, duration.getNanos());
+ }
+
+ public void testDurationInvalidFormat() throws Exception {
+ try {
+ // Value too small.
+ Duration value = Duration.newBuilder()
+ .setSeconds(TimeUtil.DURATION_SECONDS_MIN - 1).build();
+ TimeUtil.toString(value);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ // Value too large.
+ Duration value = Duration.newBuilder()
+ .setSeconds(TimeUtil.DURATION_SECONDS_MAX + 1).build();
+ TimeUtil.toString(value);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ // Invalid nanos value.
+ Duration value = Duration.newBuilder().setSeconds(1).setNanos(-1)
+ .build();
+ TimeUtil.toString(value);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ // Invalid nanos value.
+ Duration value = Duration.newBuilder().setSeconds(-1).setNanos(1)
+ .build();
+ TimeUtil.toString(value);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ // Value too small.
+ TimeUtil.parseDuration("-315576000001s");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Value too large.
+ TimeUtil.parseDuration("315576000001s");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Empty.
+ TimeUtil.parseDuration("");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Missing "s".
+ TimeUtil.parseDuration("0");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Invalid trailing data.
+ TimeUtil.parseDuration("0s0");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Invalid prefix.
+ TimeUtil.parseDuration("--1s");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+ }
+
+ public void testTimestampConversion() throws Exception {
+ Timestamp timestamp =
+ TimeUtil.parseTimestamp("1970-01-01T00:00:01.111111111Z");
+ assertEquals(1111111111, TimeUtil.toNanos(timestamp));
+ assertEquals(1111111, TimeUtil.toMicros(timestamp));
+ assertEquals(1111, TimeUtil.toMillis(timestamp));
+ timestamp = TimeUtil.createTimestampFromNanos(1111111111);
+ assertEquals("1970-01-01T00:00:01.111111111Z", TimeUtil.toString(timestamp));
+ timestamp = TimeUtil.createTimestampFromMicros(1111111);
+ assertEquals("1970-01-01T00:00:01.111111Z", TimeUtil.toString(timestamp));
+ timestamp = TimeUtil.createTimestampFromMillis(1111);
+ assertEquals("1970-01-01T00:00:01.111Z", TimeUtil.toString(timestamp));
+
+ timestamp = TimeUtil.parseTimestamp("1969-12-31T23:59:59.111111111Z");
+ assertEquals(-888888889, TimeUtil.toNanos(timestamp));
+ assertEquals(-888889, TimeUtil.toMicros(timestamp));
+ assertEquals(-889, TimeUtil.toMillis(timestamp));
+ timestamp = TimeUtil.createTimestampFromNanos(-888888889);
+ assertEquals("1969-12-31T23:59:59.111111111Z", TimeUtil.toString(timestamp));
+ timestamp = TimeUtil.createTimestampFromMicros(-888889);
+ assertEquals("1969-12-31T23:59:59.111111Z", TimeUtil.toString(timestamp));
+ timestamp = TimeUtil.createTimestampFromMillis(-889);
+ assertEquals("1969-12-31T23:59:59.111Z", TimeUtil.toString(timestamp));
+ }
+
+ public void testDurationConversion() throws Exception {
+ Duration duration = TimeUtil.parseDuration("1.111111111s");
+ assertEquals(1111111111, TimeUtil.toNanos(duration));
+ assertEquals(1111111, TimeUtil.toMicros(duration));
+ assertEquals(1111, TimeUtil.toMillis(duration));
+ duration = TimeUtil.createDurationFromNanos(1111111111);
+ assertEquals("1.111111111s", TimeUtil.toString(duration));
+ duration = TimeUtil.createDurationFromMicros(1111111);
+ assertEquals("1.111111s", TimeUtil.toString(duration));
+ duration = TimeUtil.createDurationFromMillis(1111);
+ assertEquals("1.111s", TimeUtil.toString(duration));
+
+ duration = TimeUtil.parseDuration("-1.111111111s");
+ assertEquals(-1111111111, TimeUtil.toNanos(duration));
+ assertEquals(-1111111, TimeUtil.toMicros(duration));
+ assertEquals(-1111, TimeUtil.toMillis(duration));
+ duration = TimeUtil.createDurationFromNanos(-1111111111);
+ assertEquals("-1.111111111s", TimeUtil.toString(duration));
+ duration = TimeUtil.createDurationFromMicros(-1111111);
+ assertEquals("-1.111111s", TimeUtil.toString(duration));
+ duration = TimeUtil.createDurationFromMillis(-1111);
+ assertEquals("-1.111s", TimeUtil.toString(duration));
+ }
+
+ public void testTimeOperations() throws Exception {
+ Timestamp start = TimeUtil.parseTimestamp("0001-01-01T00:00:00Z");
+ Timestamp end = TimeUtil.parseTimestamp("9999-12-31T23:59:59.999999999Z");
+
+ Duration duration = TimeUtil.distance(start, end);
+ assertEquals("315537897599.999999999s", TimeUtil.toString(duration));
+ Timestamp value = TimeUtil.add(start, duration);
+ assertEquals(end, value);
+ value = TimeUtil.subtract(end, duration);
+ assertEquals(start, value);
+
+ duration = TimeUtil.distance(end, start);
+ assertEquals("-315537897599.999999999s", TimeUtil.toString(duration));
+ value = TimeUtil.add(end, duration);
+ assertEquals(start, value);
+ value = TimeUtil.subtract(start, duration);
+ assertEquals(end, value);
+
+ // Result is larger than Long.MAX_VALUE.
+ try {
+ duration = TimeUtil.parseDuration("315537897599.999999999s");
+ duration = TimeUtil.multiply(duration, 315537897599.999999999);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ // Result is lesser than Long.MIN_VALUE.
+ try {
+ duration = TimeUtil.parseDuration("315537897599.999999999s");
+ duration = TimeUtil.multiply(duration, -315537897599.999999999);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ duration = TimeUtil.parseDuration("-1.125s");
+ duration = TimeUtil.divide(duration, 2.0);
+ assertEquals("-0.562500s", TimeUtil.toString(duration));
+ duration = TimeUtil.multiply(duration, 2.0);
+ assertEquals("-1.125s", TimeUtil.toString(duration));
+
+ duration = TimeUtil.add(duration, duration);
+ assertEquals("-2.250s", TimeUtil.toString(duration));
+
+ duration = TimeUtil.subtract(duration, TimeUtil.parseDuration("-1s"));
+ assertEquals("-1.250s", TimeUtil.toString(duration));
+
+ // Multiplications (with results larger than Long.MAX_VALUE in nanoseconds).
+ duration = TimeUtil.parseDuration("0.999999999s");
+ assertEquals("315575999684.424s",
+ TimeUtil.toString(TimeUtil.multiply(duration, 315576000000L)));
+ duration = TimeUtil.parseDuration("-0.999999999s");
+ assertEquals("-315575999684.424s",
+ TimeUtil.toString(TimeUtil.multiply(duration, 315576000000L)));
+ assertEquals("315575999684.424s",
+ TimeUtil.toString(TimeUtil.multiply(duration, -315576000000L)));
+
+ // Divisions (with values larger than Long.MAX_VALUE in nanoseconds).
+ Duration d1 = TimeUtil.parseDuration("315576000000s");
+ Duration d2 = TimeUtil.subtract(d1, TimeUtil.createDurationFromNanos(1));
+ assertEquals(1, TimeUtil.divide(d1, d2));
+ assertEquals(0, TimeUtil.divide(d2, d1));
+ assertEquals("0.000000001s", TimeUtil.toString(TimeUtil.remainder(d1, d2)));
+ assertEquals("315575999999.999999999s",
+ TimeUtil.toString(TimeUtil.remainder(d2, d1)));
+
+ // Divisions involving negative values.
+ //
+ // (-5) / 2 = -2, remainder = -1
+ d1 = TimeUtil.parseDuration("-5s");
+ d2 = TimeUtil.parseDuration("2s");
+ assertEquals(-2, TimeUtil.divide(d1, d2));
+ assertEquals(-2, TimeUtil.divide(d1, 2).getSeconds());
+ assertEquals(-1, TimeUtil.remainder(d1, d2).getSeconds());
+ // (-5) / (-2) = 2, remainder = -1
+ d1 = TimeUtil.parseDuration("-5s");
+ d2 = TimeUtil.parseDuration("-2s");
+ assertEquals(2, TimeUtil.divide(d1, d2));
+ assertEquals(2, TimeUtil.divide(d1, -2).getSeconds());
+ assertEquals(-1, TimeUtil.remainder(d1, d2).getSeconds());
+ // 5 / (-2) = -2, remainder = 1
+ d1 = TimeUtil.parseDuration("5s");
+ d2 = TimeUtil.parseDuration("-2s");
+ assertEquals(-2, TimeUtil.divide(d1, d2));
+ assertEquals(-2, TimeUtil.divide(d1, -2).getSeconds());
+ assertEquals(1, TimeUtil.remainder(d1, d2).getSeconds());
+ }
+}
diff --git a/java/util/src/test/java/com/google/protobuf/util/json_test.proto b/java/util/src/test/java/com/google/protobuf/util/json_test.proto
new file mode 100644
index 00000000..b2753af6
--- /dev/null
+++ b/java/util/src/test/java/com/google/protobuf/util/json_test.proto
@@ -0,0 +1,158 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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 json_test;
+
+option java_package = "com.google.protobuf.util";
+option java_outer_classname = "JsonTestProto";
+
+import "google/protobuf/any.proto";
+import "google/protobuf/wrappers.proto";
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/duration.proto";
+import "google/protobuf/field_mask.proto";
+import "google/protobuf/struct.proto";
+
+message TestAllTypes {
+ enum NestedEnum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ }
+ message NestedMessage {
+ int32 value = 1;
+ }
+
+ 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;
+ NestedMessage optional_nested_message = 18;
+ NestedEnum optional_nested_enum = 21;
+
+ // Repeated
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+ repeated NestedMessage repeated_nested_message = 48;
+ repeated NestedEnum repeated_nested_enum = 51;
+}
+
+message TestMap {
+ // Instead of testing all combinations (too many), we only make sure all
+ // valid types have been used at least in one field as key and in one
+ // field as value.
+ map<int32, int32> int32_to_int32_map = 1;
+ map<int64, int32> int64_to_int32_map = 2;
+ map<uint32, int32> uint32_to_int32_map = 3;
+ map<uint64, int32> uint64_to_int32_map = 4;
+ map<sint32, int32> sint32_to_int32_map = 5;
+ map<sint64, int32> sint64_to_int32_map = 6;
+ map<fixed32, int32> fixed32_to_int32_map = 7;
+ map<fixed64, int32> fixed64_to_int32_map = 8;
+ map<sfixed32, int32> sfixed32_to_int32_map = 9;
+ map<sfixed64, int32> sfixed64_to_int32_map = 10;
+ map<bool, int32> bool_to_int32_map = 11;
+ map<string, int32> string_to_int32_map = 12;
+
+ map<int32, int64> int32_to_int64_map = 101;
+ map<int32, uint32> int32_to_uint32_map = 102;
+ map<int32, uint64> int32_to_uint64_map = 103;
+ map<int32, sint32> int32_to_sint32_map = 104;
+ map<int32, sint64> int32_to_sint64_map = 105;
+ map<int32, fixed32> int32_to_fixed32_map = 106;
+ map<int32, fixed64> int32_to_fixed64_map = 107;
+ map<int32, sfixed32> int32_to_sfixed32_map = 108;
+ map<int32, sfixed64> int32_to_sfixed64_map = 109;
+ map<int32, float> int32_to_float_map = 110;
+ map<int32, double> int32_to_double_map = 111;
+ map<int32, bool> int32_to_bool_map = 112;
+ map<int32, string> int32_to_string_map = 113;
+ map<int32, bytes> int32_to_bytes_map = 114;
+ map<int32, TestAllTypes.NestedMessage> int32_to_message_map = 115;
+ map<int32, TestAllTypes.NestedEnum> int32_to_enum_map = 116;
+}
+
+message TestWrappers {
+ google.protobuf.Int32Value int32_value = 1;
+ google.protobuf.UInt32Value uint32_value = 2;
+ google.protobuf.Int64Value int64_value = 3;
+ google.protobuf.UInt64Value uint64_value = 4;
+ google.protobuf.FloatValue float_value = 5;
+ google.protobuf.DoubleValue double_value = 6;
+ google.protobuf.BoolValue bool_value = 7;
+ google.protobuf.StringValue string_value = 8;
+ google.protobuf.BytesValue bytes_value = 9;
+}
+
+message TestTimestamp {
+ google.protobuf.Timestamp timestamp_value = 1;
+}
+
+message TestDuration {
+ google.protobuf.Duration duration_value = 1;
+}
+
+message TestFieldMask {
+ google.protobuf.FieldMask field_mask_value = 1;
+}
+
+message TestStruct {
+ google.protobuf.Struct struct_value = 1;
+}
+
+message TestAny {
+ google.protobuf.Any any_value = 1;
+}
diff --git a/javanano/pom.xml b/javanano/pom.xml
index f0bcc333..1a95a43e 100644
--- a/javanano/pom.xml
+++ b/javanano/pom.xml
@@ -10,7 +10,7 @@
</parent>
<groupId>com.google.protobuf.nano</groupId>
<artifactId>protobuf-javanano</artifactId>
- <version>3.0.0-alpha-4-pre</version>
+ <version>3.0.0-alpha-4</version>
<packaging>bundle</packaging>
<name>Protocol Buffer JavaNano API</name>
<description>
@@ -165,7 +165,7 @@
<instructions>
<Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
<Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName>
- <Export-Package>com.google.protobuf;version=3.0.0-alpha-3</Export-Package>
+ <Export-Package>com.google.protobuf;version=3.0.0-alpha-4</Export-Package>
</instructions>
</configuration>
</plugin>
diff --git a/objectivec/DevTools/compile_testing_protos.sh b/objectivec/DevTools/compile_testing_protos.sh
index f414bd87..e9c5fe61 100755
--- a/objectivec/DevTools/compile_testing_protos.sh
+++ b/objectivec/DevTools/compile_testing_protos.sh
@@ -68,6 +68,7 @@ fi
mkdir -p "${OUTPUT_DIR}/google/protobuf"
CORE_PROTO_FILES=( \
+ src/google/protobuf/unittest_arena.proto \
src/google/protobuf/unittest_custom_options.proto \
src/google/protobuf/unittest_enormous_descriptor.proto \
src/google/protobuf/unittest_embed_optimize_for.proto \
@@ -76,6 +77,9 @@ CORE_PROTO_FILES=( \
src/google/protobuf/unittest_import_lite.proto \
src/google/protobuf/unittest_lite.proto \
src/google/protobuf/unittest_mset.proto \
+ src/google/protobuf/unittest_mset_wire_format.proto \
+ src/google/protobuf/unittest_no_arena.proto \
+ src/google/protobuf/unittest_no_arena_import.proto \
src/google/protobuf/unittest_no_generic_services.proto \
src/google/protobuf/unittest_optimize_for.proto \
src/google/protobuf/unittest.proto \
diff --git a/objectivec/Tests/GPBUnittestProtos.m b/objectivec/Tests/GPBUnittestProtos.m
index 0a3fc583..50c4dfa9 100644
--- a/objectivec/Tests/GPBUnittestProtos.m
+++ b/objectivec/Tests/GPBUnittestProtos.m
@@ -34,6 +34,7 @@
#import "google/protobuf/MapProto2Unittest.pbobjc.m"
#import "google/protobuf/MapUnittest.pbobjc.m"
#import "google/protobuf/Unittest.pbobjc.m"
+#import "google/protobuf/UnittestArena.pbobjc.m"
#import "google/protobuf/UnittestCustomOptions.pbobjc.m"
#import "google/protobuf/UnittestCycle.pbobjc.m"
#import "google/protobuf/UnittestDropUnknownFields.pbobjc.m"
@@ -46,6 +47,9 @@
#import "google/protobuf/UnittestImportPublicLite.pbobjc.m"
#import "google/protobuf/UnittestLite.pbobjc.m"
#import "google/protobuf/UnittestMset.pbobjc.m"
+#import "google/protobuf/UnittestMsetWireFormat.pbobjc.m"
+#import "google/protobuf/UnittestNoArena.pbobjc.m"
+#import "google/protobuf/UnittestNoArenaImport.pbobjc.m"
#import "google/protobuf/UnittestNoGenericServices.pbobjc.m"
#import "google/protobuf/UnittestObjc.pbobjc.m"
#import "google/protobuf/UnittestObjcStartup.pbobjc.m"
diff --git a/objectivec/Tests/GPBWireFormatTests.m b/objectivec/Tests/GPBWireFormatTests.m
index d722d7b2..c1244212 100644
--- a/objectivec/Tests/GPBWireFormatTests.m
+++ b/objectivec/Tests/GPBWireFormatTests.m
@@ -35,6 +35,7 @@
#import "GPBUnknownField_PackagePrivate.h"
#import "google/protobuf/Unittest.pbobjc.h"
#import "google/protobuf/UnittestMset.pbobjc.h"
+#import "google/protobuf/UnittestMsetWireFormat.pbobjc.h"
@interface WireFormatTests : GPBTestCase
@end
diff --git a/objectivec/google/protobuf/Any.pbobjc.h b/objectivec/google/protobuf/Any.pbobjc.h
index e09f3a49..6511b8ed 100644
--- a/objectivec/google/protobuf/Any.pbobjc.h
+++ b/objectivec/google/protobuf/Any.pbobjc.h
@@ -34,10 +34,8 @@ typedef GPB_ENUM(GPBAny_FieldNumber) {
// `Any` contains an arbitrary serialized message along with a URL
// that describes the type of the serialized message.
//
-// The proto runtimes and/or compiler will eventually
-// provide utilities to pack/unpack Any values (projected Q1/15).
-//
-// # JSON
+// JSON
+// ====
// The JSON representation of an `Any` value uses the regular
// representation of the deserialized, embedded message, with an
// additional field `@type` which contains the type URL. Example:
@@ -84,11 +82,6 @@ typedef GPB_ENUM(GPBAny_FieldNumber) {
//
// Schemas other than `http`, `https` (or the empty schema) might be
// used with implementation specific semantics.
-//
-// Types originating from the `google.*` package
-// namespace should use `type.googleapis.com/full.type.name` (without
-// schema and path). A type service will eventually become available which
-// serves those URLs (projected Q2/15).
@property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL;
// Must be valid serialized data of the above specified type.
diff --git a/objectivec/google/protobuf/Api.pbobjc.h b/objectivec/google/protobuf/Api.pbobjc.h
index 021dac5f..d6292cba 100644
--- a/objectivec/google/protobuf/Api.pbobjc.h
+++ b/objectivec/google/protobuf/Api.pbobjc.h
@@ -12,6 +12,7 @@
CF_EXTERN_C_BEGIN
@class GPBSourceContext;
+GPB_ENUM_FWD_DECLARE(GPBSyntax);
NS_ASSUME_NONNULL_BEGIN
@@ -34,6 +35,8 @@ typedef GPB_ENUM(GPBApi_FieldNumber) {
GPBApi_FieldNumber_OptionsArray = 3,
GPBApi_FieldNumber_Version = 4,
GPBApi_FieldNumber_SourceContext = 5,
+ GPBApi_FieldNumber_MixinsArray = 6,
+ GPBApi_FieldNumber_Syntax = 7,
};
// Api is a light-weight descriptor for a protocol buffer service.
@@ -73,8 +76,6 @@ typedef GPB_ENUM(GPBApi_FieldNumber) {
// `google.feature.v1`. For major versions 0 and 1, the suffix can
// be omitted. Zero major versions must only be used for
// experimental, none-GA apis.
-//
-// See also: [design doc](http://go/api-versioning).
@property(nonatomic, readwrite, copy, null_resettable) NSString *version;
// Source context for the protocol buffer service represented by this
@@ -82,8 +83,19 @@ typedef GPB_ENUM(GPBApi_FieldNumber) {
@property(nonatomic, readwrite) BOOL hasSourceContext;
@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext;
+// Included APIs. See [Mixin][].
+// |mixinsArray| contains |GPBMixin|
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *mixinsArray;
+@property(nonatomic, readonly) NSUInteger mixinsArray_Count;
+
+// The source syntax of the service.
+@property(nonatomic, readwrite) enum GPBSyntax syntax;
+
@end
+int32_t GPBApi_Syntax_RawValue(GPBApi *message);
+void SetGPBApi_Syntax_RawValue(GPBApi *message, int32_t value);
+
#pragma mark - GPBMethod
typedef GPB_ENUM(GPBMethod_FieldNumber) {
@@ -93,6 +105,7 @@ typedef GPB_ENUM(GPBMethod_FieldNumber) {
GPBMethod_FieldNumber_ResponseTypeURL = 4,
GPBMethod_FieldNumber_ResponseStreaming = 5,
GPBMethod_FieldNumber_OptionsArray = 6,
+ GPBMethod_FieldNumber_Syntax = 7,
};
// Method represents a method of an api.
@@ -118,6 +131,108 @@ typedef GPB_ENUM(GPBMethod_FieldNumber) {
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray;
@property(nonatomic, readonly) NSUInteger optionsArray_Count;
+// The source syntax of this method.
+@property(nonatomic, readwrite) enum GPBSyntax syntax;
+
+@end
+
+int32_t GPBMethod_Syntax_RawValue(GPBMethod *message);
+void SetGPBMethod_Syntax_RawValue(GPBMethod *message, int32_t value);
+
+#pragma mark - GPBMixin
+
+typedef GPB_ENUM(GPBMixin_FieldNumber) {
+ GPBMixin_FieldNumber_Name = 1,
+ GPBMixin_FieldNumber_Root = 2,
+};
+
+// Declares an API to be included in this API. The including API must
+// redeclare all the methods from the included API, but documentation
+// and options are inherited as follows:
+//
+// - If after comment and whitespace stripping, the documentation
+// string of the redeclared method is empty, it will be inherited
+// from the original method.
+//
+// - Each annotation belonging to the service config (http,
+// visibility) which is not set in the redeclared method will be
+// inherited.
+//
+// - If an http annotation is inherited, the path pattern will be
+// modified as follows. Any version prefix will be replaced by the
+// version of the including API plus the [root][] path if specified.
+//
+// Example of a simple mixin:
+//
+// package google.acl.v1;
+// service AccessControl {
+// // Get the underlying ACL object.
+// rpc GetAcl(GetAclRequest) returns (Acl) {
+// option (google.api.http).get = "/v1/{resource=**}:getAcl";
+// }
+// }
+//
+// package google.storage.v2;
+// service Storage {
+// // (-- see AccessControl.GetAcl --)
+// rpc GetAcl(GetAclRequest) returns (Acl);
+//
+// // Get a data record.
+// rpc GetData(GetDataRequest) returns (Data) {
+// option (google.api.http).get = "/v2/{resource=**}";
+// }
+// }
+//
+// Example of a mixin configuration:
+//
+// apis:
+// - name: google.storage.v2.Storage
+// mixins:
+// - name: google.acl.v1.AccessControl
+//
+// The mixin construct implies that all methods in `AccessControl` are
+// also declared with same name and request/response types in
+// `Storage`. A documentation generator or annotation processor will
+// see the effective `Storage.GetAcl` method after inherting
+// documentation and annotations as follows:
+//
+// service Storage {
+// // Get the underlying ACL object.
+// rpc GetAcl(GetAclRequest) returns (Acl) {
+// option (google.api.http).get = "/v2/{resource=**}:getAcl";
+// }
+// ...
+// }
+//
+// Note how the version in the path pattern changed from `v1` to `v2`.
+//
+// If the `root` field in the mixin is specified, it should be a
+// relative path under which inherited HTTP paths are placed. Example:
+//
+// apis:
+// - name: google.storage.v2.Storage
+// mixins:
+// - name: google.acl.v1.AccessControl
+// root: acls
+//
+// This implies the following inherited HTTP annotation:
+//
+// service Storage {
+// // Get the underlying ACL object.
+// rpc GetAcl(GetAclRequest) returns (Acl) {
+// option (google.api.http).get = "/v2/acls/{resource=**}:getAcl";
+// }
+// ...
+// }
+@interface GPBMixin : GPBMessage
+
+// The fully qualified name of the API which is included.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
+
+// If non-empty specifies a path under which inherited HTTP paths
+// are rooted.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *root;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/objectivec/google/protobuf/Api.pbobjc.m b/objectivec/google/protobuf/Api.pbobjc.m
index c2be94ab..d964ff41 100644
--- a/objectivec/google/protobuf/Api.pbobjc.m
+++ b/objectivec/google/protobuf/Api.pbobjc.m
@@ -49,14 +49,18 @@ static GPBFileDescriptor *GPBApiRoot_FileDescriptor(void) {
@dynamic optionsArray, optionsArray_Count;
@dynamic version;
@dynamic hasSourceContext, sourceContext;
+@dynamic mixinsArray, mixinsArray_Count;
+@dynamic syntax;
typedef struct GPBApi__storage_ {
uint32_t _has_storage_[1];
+ GPBSyntax syntax;
NSString *name;
NSMutableArray *methodsArray;
NSMutableArray *optionsArray;
NSString *version;
GPBSourceContext *sourceContext;
+ NSMutableArray *mixinsArray;
} GPBApi__storage_;
// This method is threadsafe because it is initially called
@@ -120,6 +124,28 @@ typedef struct GPBApi__storage_ {
.dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext),
.fieldOptions = NULL,
},
+ {
+ .name = "mixinsArray",
+ .number = GPBApi_FieldNumber_MixinsArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .dataType = GPBDataTypeMessage,
+ .offset = offsetof(GPBApi__storage_, mixinsArray),
+ .defaultValue.valueMessage = nil,
+ .dataTypeSpecific.className = GPBStringifySymbol(GPBMixin),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "syntax",
+ .number = GPBApi_FieldNumber_Syntax,
+ .hasIndex = 6,
+ .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+ .dataType = GPBDataTypeEnum,
+ .offset = offsetof(GPBApi__storage_, syntax),
+ .defaultValue.valueEnum = GPBSyntax_SyntaxProto2,
+ .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor,
+ .fieldOptions = NULL,
+ },
};
GPBDescriptor *localDescriptor =
[GPBDescriptor allocDescriptorForClass:[GPBApi class]
@@ -143,6 +169,18 @@ typedef struct GPBApi__storage_ {
@end
+int32_t GPBApi_Syntax_RawValue(GPBApi *message) {
+ GPBDescriptor *descriptor = [GPBApi descriptor];
+ GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax];
+ return GPBGetMessageInt32Field(message, field);
+}
+
+void SetGPBApi_Syntax_RawValue(GPBApi *message, int32_t value) {
+ GPBDescriptor *descriptor = [GPBApi descriptor];
+ GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax];
+ GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+}
+
#pragma mark - GPBMethod
@implementation GPBMethod
@@ -153,11 +191,13 @@ typedef struct GPBApi__storage_ {
@dynamic responseTypeURL;
@dynamic responseStreaming;
@dynamic optionsArray, optionsArray_Count;
+@dynamic syntax;
typedef struct GPBMethod__storage_ {
uint32_t _has_storage_[1];
BOOL requestStreaming;
BOOL responseStreaming;
+ GPBSyntax syntax;
NSString *name;
NSString *requestTypeURL;
NSString *responseTypeURL;
@@ -236,6 +276,17 @@ typedef struct GPBMethod__storage_ {
.dataTypeSpecific.className = GPBStringifySymbol(GPBOption),
.fieldOptions = NULL,
},
+ {
+ .name = "syntax",
+ .number = GPBMethod_FieldNumber_Syntax,
+ .hasIndex = 6,
+ .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+ .dataType = GPBDataTypeEnum,
+ .offset = offsetof(GPBMethod__storage_, syntax),
+ .defaultValue.valueEnum = GPBSyntax_SyntaxProto2,
+ .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor,
+ .fieldOptions = NULL,
+ },
};
#if GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
const char *extraTextFormatInfo = NULL;
@@ -265,5 +316,81 @@ typedef struct GPBMethod__storage_ {
@end
+int32_t GPBMethod_Syntax_RawValue(GPBMethod *message) {
+ GPBDescriptor *descriptor = [GPBMethod descriptor];
+ GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax];
+ return GPBGetMessageInt32Field(message, field);
+}
+
+void SetGPBMethod_Syntax_RawValue(GPBMethod *message, int32_t value) {
+ GPBDescriptor *descriptor = [GPBMethod descriptor];
+ GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax];
+ GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+}
+
+#pragma mark - GPBMixin
+
+@implementation GPBMixin
+
+@dynamic name;
+@dynamic root;
+
+typedef struct GPBMixin__storage_ {
+ uint32_t _has_storage_[1];
+ NSString *name;
+ NSString *root;
+} GPBMixin__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = nil;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "name",
+ .number = GPBMixin_FieldNumber_Name,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional,
+ .dataType = GPBDataTypeString,
+ .offset = offsetof(GPBMixin__storage_, name),
+ .defaultValue.valueString = nil,
+ .dataTypeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "root",
+ .number = GPBMixin_FieldNumber_Root,
+ .hasIndex = 1,
+ .flags = GPBFieldOptional,
+ .dataType = GPBDataTypeString,
+ .offset = offsetof(GPBMixin__storage_, root),
+ .defaultValue.valueString = nil,
+ .dataTypeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ };
+ GPBDescriptor *localDescriptor =
+ [GPBDescriptor allocDescriptorForClass:[GPBMixin class]
+ rootClass:[GPBApiRoot class]
+ file:GPBApiRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBMixin__storage_)
+ wireFormat:NO];
+ NSAssert(descriptor == nil, @"Startup recursed!");
+ descriptor = localDescriptor;
+ }
+ return descriptor;
+}
+
+@end
+
// @@protoc_insertion_point(global_scope)
diff --git a/objectivec/google/protobuf/Descriptor.pbobjc.h b/objectivec/google/protobuf/Descriptor.pbobjc.h
index bf0f51a6..2a86a7e1 100644
--- a/objectivec/google/protobuf/Descriptor.pbobjc.h
+++ b/objectivec/google/protobuf/Descriptor.pbobjc.h
@@ -531,6 +531,7 @@ typedef GPB_ENUM(GPBFileOptions_FieldNumber) {
GPBFileOptions_FieldNumber_CcEnableArenas = 31,
GPBFileOptions_FieldNumber_ObjcClassPrefix = 36,
GPBFileOptions_FieldNumber_CsharpNamespace = 37,
+ GPBFileOptions_FieldNumber_JavananoUseDeprecatedPackage = 38,
GPBFileOptions_FieldNumber_UninterpretedOptionArray = 999,
};
@@ -562,10 +563,12 @@ typedef GPB_ENUM(GPBFileOptions_FieldNumber) {
// If set true, then the Java code generator will generate equals() and
// hashCode() methods for all messages defined in the .proto file.
-// - In the full runtime, this is purely a speed optimization, as the
+// This increases generated code size, potentially substantially for large
+// protos, which may harm a memory-constrained application.
+// - In the full runtime this is a speed optimization, as the
// AbstractMessage base class includes reflection-based implementations of
// these methods.
-//- In the lite runtime, setting this option changes the semantics of
+// - In the lite runtime, setting this option changes the semantics of
// equals() and hashCode() to more closely match those of the full runtime;
// the generated methods compute their results based on field values rather
// than object identity. (Implementations should not assume that hashcodes
@@ -633,6 +636,11 @@ typedef GPB_ENUM(GPBFileOptions_FieldNumber) {
@property(nonatomic, readwrite) BOOL hasCsharpNamespace;
@property(nonatomic, readwrite, copy, null_resettable) NSString *csharpNamespace;
+// Whether the nano proto compiler should generate in the deprecated non-nano
+// suffixed package.
+@property(nonatomic, readwrite) BOOL hasJavananoUseDeprecatedPackage;
+@property(nonatomic, readwrite) BOOL javananoUseDeprecatedPackage;
+
// The parser stores options it doesn't recognize here. See above.
// |uninterpretedOptionArray| contains |GPBUninterpretedOption|
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *uninterpretedOptionArray;
diff --git a/objectivec/google/protobuf/Descriptor.pbobjc.m b/objectivec/google/protobuf/Descriptor.pbobjc.m
index 8c535b9a..8d69867b 100644
--- a/objectivec/google/protobuf/Descriptor.pbobjc.m
+++ b/objectivec/google/protobuf/Descriptor.pbobjc.m
@@ -1229,6 +1229,7 @@ typedef struct GPBMethodDescriptorProto__storage_ {
@dynamic hasCcEnableArenas, ccEnableArenas;
@dynamic hasObjcClassPrefix, objcClassPrefix;
@dynamic hasCsharpNamespace, csharpNamespace;
+@dynamic hasJavananoUseDeprecatedPackage, javananoUseDeprecatedPackage;
@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count;
typedef struct GPBFileOptions__storage_ {
@@ -1241,6 +1242,7 @@ typedef struct GPBFileOptions__storage_ {
BOOL deprecated;
BOOL javaStringCheckUtf8;
BOOL ccEnableArenas;
+ BOOL javananoUseDeprecatedPackage;
GPBFileOptions_OptimizeMode optimizeFor;
NSString *javaPackage;
NSString *javaOuterClassname;
@@ -1411,6 +1413,17 @@ typedef struct GPBFileOptions__storage_ {
.fieldOptions = NULL,
},
{
+ .name = "javananoUseDeprecatedPackage",
+ .number = GPBFileOptions_FieldNumber_JavananoUseDeprecatedPackage,
+ .hasIndex = 14,
+ .flags = GPBFieldOptional,
+ .dataType = GPBDataTypeBool,
+ .offset = offsetof(GPBFileOptions__storage_, javananoUseDeprecatedPackage),
+ .defaultValue.valueBool = NO,
+ .dataTypeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
.name = "uninterpretedOptionArray",
.number = GPBFileOptions_FieldNumber_UninterpretedOptionArray,
.hasIndex = GPBNoHasBit,
diff --git a/objectivec/google/protobuf/Empty.pbobjc.h b/objectivec/google/protobuf/Empty.pbobjc.h
index 17e2b19b..ff7f384a 100644
--- a/objectivec/google/protobuf/Empty.pbobjc.h
+++ b/objectivec/google/protobuf/Empty.pbobjc.h
@@ -33,6 +33,8 @@ NS_ASSUME_NONNULL_BEGIN
// service Foo {
// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
// }
+//
+// The JSON representation for `Empty` is empty JSON object `{}`.
@interface GPBEmpty : GPBMessage
@end
diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.h b/objectivec/google/protobuf/FieldMask.pbobjc.h
index de62c03b..0cdbd574 100644
--- a/objectivec/google/protobuf/FieldMask.pbobjc.h
+++ b/objectivec/google/protobuf/FieldMask.pbobjc.h
@@ -44,6 +44,7 @@ typedef GPB_ENUM(GPBFieldMask_FieldNumber) {
// Field masks also have a custom JSON encoding (see below).
//
// # Field Masks in Projections
+//
// When used in the context of a projection, a response message or
// sub-message is filtered by the API to only contain those fields as
// specified in the mask. For example, if the mask in the previous
@@ -89,6 +90,7 @@ typedef GPB_ENUM(GPBFieldMask_FieldNumber) {
// behavior for APIs.
//
// # Field Masks in Update Operations
+//
// A field mask in update operations specifies which fields of the
// targeted resource are going to be updated. The API is required
// to only change the values of the fields as specified in the mask
@@ -116,11 +118,13 @@ typedef GPB_ENUM(GPBFieldMask_FieldNumber) {
// required to be honored by the API.
//
// ## Considerations for HTTP REST
+//
// The HTTP kind of an update operation which uses a field mask must
// be set to PATCH instead of PUT in order to satisfy HTTP semantics
// (PUT must only be used for full updates).
//
// # JSON Encoding of Field Masks
+//
// In JSON, a field mask is encoded as a single string where paths are
// separated by a comma. Fields name in each path are converted
// to/from lower-camel naming conventions.
diff --git a/objectivec/google/protobuf/Struct.pbobjc.h b/objectivec/google/protobuf/Struct.pbobjc.h
index d72f9738..7513cf90 100644
--- a/objectivec/google/protobuf/Struct.pbobjc.h
+++ b/objectivec/google/protobuf/Struct.pbobjc.h
@@ -18,8 +18,10 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Enum GPBNullValue
-// `NullValue` is a singleton enumeration to represent the null
-// value for the `Value` type union.
+// `NullValue` is a singleton enumeration to represent the null value for the
+// `Value` type union.
+//
+// The JSON representation for `NullValue` is JSON `null`.
typedef GPB_ENUM(GPBNullValue) {
GPBNullValue_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,
// Null value.
@@ -53,6 +55,8 @@ typedef GPB_ENUM(GPBStruct_FieldNumber) {
// scripting languages like JS a struct is represented as an
// object. The details of that representation are described together
// with the proto support for the language.
+//
+// The JSON representation for `Struct` is JSON object.
@interface GPBStruct : GPBMessage
// Map of dynamically typed values.
@@ -87,8 +91,11 @@ typedef GPB_ENUM(GPBValue_Kind_OneOfCase) {
// null, a number, a string, a boolean, a recursive struct value, or a
// list of values. A producer of value is expected to set one of that
// variants, absence of any variant indicates an error.
+//
+// The JSON representation for `Value` is JSON value.
@interface GPBValue : GPBMessage
+// The kind of value.
@property(nonatomic, readonly) GPBValue_Kind_OneOfCase kindOneOfCase;
// Represents a null value.
@@ -123,6 +130,8 @@ typedef GPB_ENUM(GPBListValue_FieldNumber) {
};
// `ListValue` is a wrapper around a repeated field of values.
+//
+// The JSON representation for `ListValue` is JSON array.
@interface GPBListValue : GPBMessage
// Repeated field of dynamically typed values.
diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.h b/objectivec/google/protobuf/Timestamp.pbobjc.h
index 0b342156..a1f68bd2 100644
--- a/objectivec/google/protobuf/Timestamp.pbobjc.h
+++ b/objectivec/google/protobuf/Timestamp.pbobjc.h
@@ -77,11 +77,12 @@ typedef GPB_ENUM(GPBTimestamp_FieldNumber) {
// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
// .setNanos((int) ((millis % 1000) * 1000000)).build();
//
-// Example 5: Compute Timestamp from Python `datetime.datetime`.
//
-// now = datetime.datetime.utcnow()
-// seconds = int(time.mktime(now.timetuple()))
-// nanos = now.microsecond * 1000
+// Example 5: Compute Timestamp from current time in Python.
+//
+// now = time.time()
+// seconds = int(now)
+// nanos = int((now - seconds) * 10**9)
// timestamp = Timestamp(seconds=seconds, nanos=nanos)
@interface GPBTimestamp : GPBMessage
diff --git a/objectivec/google/protobuf/Type.pbobjc.h b/objectivec/google/protobuf/Type.pbobjc.h
index eb807ae5..44ef05c5 100644
--- a/objectivec/google/protobuf/Type.pbobjc.h
+++ b/objectivec/google/protobuf/Type.pbobjc.h
@@ -16,6 +16,22 @@ CF_EXTERN_C_BEGIN
NS_ASSUME_NONNULL_BEGIN
+#pragma mark - Enum GPBSyntax
+
+// Syntax specifies the syntax in which a service element was defined.
+typedef GPB_ENUM(GPBSyntax) {
+ GPBSyntax_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,
+ // Syntax "proto2"
+ GPBSyntax_SyntaxProto2 = 0,
+
+ // Syntax "proto3"
+ GPBSyntax_SyntaxProto3 = 1,
+};
+
+GPBEnumDescriptor *GPBSyntax_EnumDescriptor(void);
+
+BOOL GPBSyntax_IsValidValue(int32_t value);
+
#pragma mark - Enum GPBField_Kind
// Kind represents a basic field type.
@@ -51,6 +67,9 @@ typedef GPB_ENUM(GPBField_Kind) {
// Field type string.
GPBField_Kind_TypeString = 9,
+ // Field type group (deprecated proto2 type)
+ GPBField_Kind_TypeGroup = 10,
+
// Field type message.
GPBField_Kind_TypeMessage = 11,
@@ -122,6 +141,7 @@ typedef GPB_ENUM(GPBType_FieldNumber) {
GPBType_FieldNumber_OneofsArray = 3,
GPBType_FieldNumber_OptionsArray = 4,
GPBType_FieldNumber_SourceContext = 5,
+ GPBType_FieldNumber_Syntax = 6,
};
// A light-weight descriptor for a proto message type.
@@ -136,7 +156,6 @@ typedef GPB_ENUM(GPBType_FieldNumber) {
@property(nonatomic, readonly) NSUInteger fieldsArray_Count;
// The list of oneof definitions.
-// The list of oneofs declared in this Type
// |oneofsArray| contains |NSString|
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *oneofsArray;
@property(nonatomic, readonly) NSUInteger oneofsArray_Count;
@@ -150,8 +169,14 @@ typedef GPB_ENUM(GPBType_FieldNumber) {
@property(nonatomic, readwrite) BOOL hasSourceContext;
@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext;
+// The source syntax.
+@property(nonatomic, readwrite) GPBSyntax syntax;
+
@end
+int32_t GPBType_Syntax_RawValue(GPBType *message);
+void SetGPBType_Syntax_RawValue(GPBType *message, int32_t value);
+
#pragma mark - GPBField
typedef GPB_ENUM(GPBField_FieldNumber) {
@@ -163,6 +188,7 @@ typedef GPB_ENUM(GPBField_FieldNumber) {
GPBField_FieldNumber_OneofIndex = 7,
GPBField_FieldNumber_Packed = 8,
GPBField_FieldNumber_OptionsArray = 9,
+ GPBField_FieldNumber_JsonName = 10,
};
// Field represents a single field of a message type.
@@ -195,6 +221,9 @@ typedef GPB_ENUM(GPBField_FieldNumber) {
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray;
@property(nonatomic, readonly) NSUInteger optionsArray_Count;
+// The JSON name for this field.
+@property(nonatomic, readwrite, copy, null_resettable) NSString *jsonName;
+
@end
int32_t GPBField_Kind_RawValue(GPBField *message);
@@ -210,6 +239,7 @@ typedef GPB_ENUM(GPBEnum_FieldNumber) {
GPBEnum_FieldNumber_EnumvalueArray = 2,
GPBEnum_FieldNumber_OptionsArray = 3,
GPBEnum_FieldNumber_SourceContext = 4,
+ GPBEnum_FieldNumber_Syntax = 5,
};
// Enum type definition.
@@ -232,8 +262,14 @@ typedef GPB_ENUM(GPBEnum_FieldNumber) {
@property(nonatomic, readwrite) BOOL hasSourceContext;
@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext;
+// The source syntax.
+@property(nonatomic, readwrite) GPBSyntax syntax;
+
@end
+int32_t GPBEnum_Syntax_RawValue(GPBEnum *message);
+void SetGPBEnum_Syntax_RawValue(GPBEnum *message, int32_t value);
+
#pragma mark - GPBEnumValue
typedef GPB_ENUM(GPBEnumValue_FieldNumber) {
diff --git a/objectivec/google/protobuf/Type.pbobjc.m b/objectivec/google/protobuf/Type.pbobjc.m
index 5a2ce282..4485e904 100644
--- a/objectivec/google/protobuf/Type.pbobjc.m
+++ b/objectivec/google/protobuf/Type.pbobjc.m
@@ -40,6 +40,33 @@ static GPBFileDescriptor *GPBTypeRoot_FileDescriptor(void) {
return descriptor;
}
+#pragma mark - Enum GPBSyntax
+
+GPBEnumDescriptor *GPBSyntax_EnumDescriptor(void) {
+ static GPBEnumDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageEnumValueDescription values[] = {
+ { .name = "SyntaxProto2", .number = GPBSyntax_SyntaxProto2 },
+ { .name = "SyntaxProto3", .number = GPBSyntax_SyntaxProto3 },
+ };
+ descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBSyntax)
+ values:values
+ valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)
+ enumVerifier:GPBSyntax_IsValidValue];
+ }
+ return descriptor;
+}
+
+BOOL GPBSyntax_IsValidValue(int32_t value__) {
+ switch (value__) {
+ case GPBSyntax_SyntaxProto2:
+ case GPBSyntax_SyntaxProto3:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
#pragma mark - GPBType
@implementation GPBType
@@ -49,9 +76,11 @@ static GPBFileDescriptor *GPBTypeRoot_FileDescriptor(void) {
@dynamic oneofsArray, oneofsArray_Count;
@dynamic optionsArray, optionsArray_Count;
@dynamic hasSourceContext, sourceContext;
+@dynamic syntax;
typedef struct GPBType__storage_ {
uint32_t _has_storage_[1];
+ GPBSyntax syntax;
NSString *name;
NSMutableArray *fieldsArray;
NSMutableArray *oneofsArray;
@@ -120,6 +149,17 @@ typedef struct GPBType__storage_ {
.dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext),
.fieldOptions = NULL,
},
+ {
+ .name = "syntax",
+ .number = GPBType_FieldNumber_Syntax,
+ .hasIndex = 5,
+ .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+ .dataType = GPBDataTypeEnum,
+ .offset = offsetof(GPBType__storage_, syntax),
+ .defaultValue.valueEnum = GPBSyntax_SyntaxProto2,
+ .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor,
+ .fieldOptions = NULL,
+ },
};
GPBDescriptor *localDescriptor =
[GPBDescriptor allocDescriptorForClass:[GPBType class]
@@ -143,6 +183,18 @@ typedef struct GPBType__storage_ {
@end
+int32_t GPBType_Syntax_RawValue(GPBType *message) {
+ GPBDescriptor *descriptor = [GPBType descriptor];
+ GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax];
+ return GPBGetMessageInt32Field(message, field);
+}
+
+void SetGPBType_Syntax_RawValue(GPBType *message, int32_t value) {
+ GPBDescriptor *descriptor = [GPBType descriptor];
+ GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax];
+ GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+}
+
#pragma mark - GPBField
@implementation GPBField
@@ -155,6 +207,7 @@ typedef struct GPBType__storage_ {
@dynamic oneofIndex;
@dynamic packed;
@dynamic optionsArray, optionsArray_Count;
+@dynamic jsonName;
typedef struct GPBField__storage_ {
uint32_t _has_storage_[1];
@@ -166,6 +219,7 @@ typedef struct GPBField__storage_ {
NSString *name;
NSString *typeURL;
NSMutableArray *optionsArray;
+ NSString *jsonName;
} GPBField__storage_;
// This method is threadsafe because it is initially called
@@ -262,6 +316,17 @@ typedef struct GPBField__storage_ {
.dataTypeSpecific.className = GPBStringifySymbol(GPBOption),
.fieldOptions = NULL,
},
+ {
+ .name = "jsonName",
+ .number = GPBField_FieldNumber_JsonName,
+ .hasIndex = 8,
+ .flags = GPBFieldOptional,
+ .dataType = GPBDataTypeString,
+ .offset = offsetof(GPBField__storage_, jsonName),
+ .defaultValue.valueString = nil,
+ .dataTypeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
};
static GPBMessageEnumDescription enums[] = {
{ .enumDescriptorFunc = GPBField_Kind_EnumDescriptor },
@@ -335,6 +400,7 @@ GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void) {
{ .name = "TypeFixed32", .number = GPBField_Kind_TypeFixed32 },
{ .name = "TypeBool", .number = GPBField_Kind_TypeBool },
{ .name = "TypeString", .number = GPBField_Kind_TypeString },
+ { .name = "TypeGroup", .number = GPBField_Kind_TypeGroup },
{ .name = "TypeMessage", .number = GPBField_Kind_TypeMessage },
{ .name = "TypeBytes", .number = GPBField_Kind_TypeBytes },
{ .name = "TypeUint32", .number = GPBField_Kind_TypeUint32 },
@@ -364,6 +430,7 @@ BOOL GPBField_Kind_IsValidValue(int32_t value__) {
case GPBField_Kind_TypeFixed32:
case GPBField_Kind_TypeBool:
case GPBField_Kind_TypeString:
+ case GPBField_Kind_TypeGroup:
case GPBField_Kind_TypeMessage:
case GPBField_Kind_TypeBytes:
case GPBField_Kind_TypeUint32:
@@ -417,9 +484,11 @@ BOOL GPBField_Cardinality_IsValidValue(int32_t value__) {
@dynamic enumvalueArray, enumvalueArray_Count;
@dynamic optionsArray, optionsArray_Count;
@dynamic hasSourceContext, sourceContext;
+@dynamic syntax;
typedef struct GPBEnum__storage_ {
uint32_t _has_storage_[1];
+ GPBSyntax syntax;
NSString *name;
NSMutableArray *enumvalueArray;
NSMutableArray *optionsArray;
@@ -476,6 +545,17 @@ typedef struct GPBEnum__storage_ {
.dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext),
.fieldOptions = NULL,
},
+ {
+ .name = "syntax",
+ .number = GPBEnum_FieldNumber_Syntax,
+ .hasIndex = 4,
+ .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+ .dataType = GPBDataTypeEnum,
+ .offset = offsetof(GPBEnum__storage_, syntax),
+ .defaultValue.valueEnum = GPBSyntax_SyntaxProto2,
+ .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor,
+ .fieldOptions = NULL,
+ },
};
GPBDescriptor *localDescriptor =
[GPBDescriptor allocDescriptorForClass:[GPBEnum class]
@@ -499,6 +579,18 @@ typedef struct GPBEnum__storage_ {
@end
+int32_t GPBEnum_Syntax_RawValue(GPBEnum *message) {
+ GPBDescriptor *descriptor = [GPBEnum descriptor];
+ GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax];
+ return GPBGetMessageInt32Field(message, field);
+}
+
+void SetGPBEnum_Syntax_RawValue(GPBEnum *message, int32_t value) {
+ GPBDescriptor *descriptor = [GPBEnum descriptor];
+ GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax];
+ GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
+}
+
#pragma mark - GPBEnumValue
@implementation GPBEnumValue
diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.h b/objectivec/google/protobuf/Wrappers.pbobjc.h
index b4718d02..a9a260bc 100644
--- a/objectivec/google/protobuf/Wrappers.pbobjc.h
+++ b/objectivec/google/protobuf/Wrappers.pbobjc.h
@@ -30,7 +30,9 @@ typedef GPB_ENUM(GPBDoubleValue_FieldNumber) {
GPBDoubleValue_FieldNumber_Value = 1,
};
-// Wrapper message for double.
+// Wrapper message for `double`.
+//
+// The JSON representation for `DoubleValue` is JSON number.
@interface GPBDoubleValue : GPBMessage
// The double value.
@@ -44,7 +46,9 @@ typedef GPB_ENUM(GPBFloatValue_FieldNumber) {
GPBFloatValue_FieldNumber_Value = 1,
};
-// Wrapper message for float.
+// Wrapper message for `float`.
+//
+// The JSON representation for `FloatValue` is JSON number.
@interface GPBFloatValue : GPBMessage
// The float value.
@@ -58,7 +62,9 @@ typedef GPB_ENUM(GPBInt64Value_FieldNumber) {
GPBInt64Value_FieldNumber_Value = 1,
};
-// Wrapper message for int64.
+// Wrapper message for `int64`.
+//
+// The JSON representation for `Int64Value` is JSON string.
@interface GPBInt64Value : GPBMessage
// The int64 value.
@@ -72,7 +78,9 @@ typedef GPB_ENUM(GPBUInt64Value_FieldNumber) {
GPBUInt64Value_FieldNumber_Value = 1,
};
-// Wrapper message for uint64.
+// Wrapper message for `uint64`.
+//
+// The JSON representation for `UInt64Value` is JSON string.
@interface GPBUInt64Value : GPBMessage
// The uint64 value.
@@ -86,7 +94,9 @@ typedef GPB_ENUM(GPBInt32Value_FieldNumber) {
GPBInt32Value_FieldNumber_Value = 1,
};
-// Wrapper message for int32.
+// Wrapper message for `int32`.
+//
+// The JSON representation for `Int32Value` is JSON number.
@interface GPBInt32Value : GPBMessage
// The int32 value.
@@ -100,7 +110,9 @@ typedef GPB_ENUM(GPBUInt32Value_FieldNumber) {
GPBUInt32Value_FieldNumber_Value = 1,
};
-// Wrapper message for uint32.
+// Wrapper message for `uint32`.
+//
+// The JSON representation for `UInt32Value` is JSON number.
@interface GPBUInt32Value : GPBMessage
// The uint32 value.
@@ -114,7 +126,9 @@ typedef GPB_ENUM(GPBBoolValue_FieldNumber) {
GPBBoolValue_FieldNumber_Value = 1,
};
-// Wrapper message for bool.
+// Wrapper message for `bool`.
+//
+// The JSON representation for `BoolValue` is JSON `true` and `false`.
@interface GPBBoolValue : GPBMessage
// The bool value.
@@ -128,7 +142,9 @@ typedef GPB_ENUM(GPBStringValue_FieldNumber) {
GPBStringValue_FieldNumber_Value = 1,
};
-// Wrapper message for string.
+// Wrapper message for `string`.
+//
+// The JSON representation for `StringValue` is JSON string.
@interface GPBStringValue : GPBMessage
// The string value.
@@ -142,7 +158,9 @@ typedef GPB_ENUM(GPBBytesValue_FieldNumber) {
GPBBytesValue_FieldNumber_Value = 1,
};
-// Wrapper message for bytes.
+// Wrapper message for `bytes`.
+//
+// The JSON representation for `BytesValue` is JSON string.
@interface GPBBytesValue : GPBMessage
// The bytes value.
diff --git a/post_process_dist.sh b/post_process_dist.sh
index 05113af1..6d5b85d3 100755
--- a/post_process_dist.sh
+++ b/post_process_dist.sh
@@ -40,11 +40,7 @@ rm $BASENAME.tar.gz
# Set the entire contents to be user-writable.
chmod -R u+w $BASENAME
-
-# Convert the MSVC projects to MSVC 2005 format.
-cd $BASENAME/vsprojects
-./convert2008to2005.sh
-cd ..
+cd $BASENAME
for LANG in $LANGUAGES; do
# Build the dist again in .tar.gz
diff --git a/protoc-artifacts/pom.xml b/protoc-artifacts/pom.xml
index 52a7d2d6..cdf17707 100644
--- a/protoc-artifacts/pom.xml
+++ b/protoc-artifacts/pom.xml
@@ -10,7 +10,7 @@
</parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protoc</artifactId>
- <version>3.0.0-alpha-4-pre</version>
+ <version>3.0.0-beta-1</version>
<packaging>pom</packaging>
<name>Protobuf Compiler</name>
<description>
diff --git a/python/google/protobuf/__init__.py b/python/google/protobuf/__init__.py
index 50343c89..ed88480f 100755
--- a/python/google/protobuf/__init__.py
+++ b/python/google/protobuf/__init__.py
@@ -30,4 +30,4 @@
# Copyright 2007 Google Inc. All Rights Reserved.
-__version__ = '3.0.0a4.dev0'
+__version__ = '3.0.0a4'
diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py
index 72c2fa01..9c8275eb 100755
--- a/python/google/protobuf/internal/containers.py
+++ b/python/google/protobuf/internal/containers.py
@@ -41,6 +41,7 @@ are:
__author__ = 'petar@google.com (Petar Petrov)'
+import collections
import sys
if sys.version_info[0] < 3:
@@ -63,7 +64,6 @@ if sys.version_info[0] < 3:
# Note: deriving from object is critical. It is the only thing that makes
# this a true type, allowing us to derive from it in C++ cleanly and making
# __slots__ properly disallow arbitrary element assignment.
- from collections import Mapping as _Mapping
class Mapping(object):
__slots__ = ()
@@ -106,7 +106,7 @@ if sys.version_info[0] < 3:
__hash__ = None
def __eq__(self, other):
- if not isinstance(other, _Mapping):
+ if not isinstance(other, collections.Mapping):
return NotImplemented
return dict(self.items()) == dict(other.items())
@@ -173,12 +173,13 @@ if sys.version_info[0] < 3:
self[key] = default
return default
- _Mapping.register(Mapping)
+ collections.Mapping.register(Mapping)
+ collections.MutableMapping.register(MutableMapping)
else:
# In Python 3 we can just use MutableMapping directly, because it defines
# __slots__.
- from collections import MutableMapping
+ MutableMapping = collections.MutableMapping
class BaseContainer(object):
@@ -336,6 +337,8 @@ class RepeatedScalarFieldContainer(BaseContainer):
# We are presumably comparing against some other sequence type.
return other == self._values
+collections.MutableSequence.register(BaseContainer)
+
class RepeatedCompositeFieldContainer(BaseContainer):
diff --git a/python/google/protobuf/internal/generator_test.py b/python/google/protobuf/internal/generator_test.py
index bdd7382a..9956da59 100755
--- a/python/google/protobuf/internal/generator_test.py
+++ b/python/google/protobuf/internal/generator_test.py
@@ -50,6 +50,7 @@ from google.protobuf import unittest_custom_options_pb2
from google.protobuf import unittest_import_pb2
from google.protobuf import unittest_import_public_pb2
from google.protobuf import unittest_mset_pb2
+from google.protobuf import unittest_mset_wire_format_pb2
from google.protobuf import unittest_no_generic_services_pb2
from google.protobuf import unittest_pb2
from google.protobuf import service
@@ -145,7 +146,7 @@ class GeneratorTest(unittest.TestCase):
self.assertTrue(not non_extension_descriptor.is_extension)
def testOptions(self):
- proto = unittest_mset_pb2.TestMessageSet()
+ proto = unittest_mset_wire_format_pb2.TestMessageSet()
self.assertTrue(proto.DESCRIPTOR.GetOptions().message_set_wire_format)
def testMessageWithCustomOptions(self):
diff --git a/python/google/protobuf/internal/message_set_extensions.proto b/python/google/protobuf/internal/message_set_extensions.proto
new file mode 100644
index 00000000..702c8d07
--- /dev/null
+++ b/python/google/protobuf/internal/message_set_extensions.proto
@@ -0,0 +1,66 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file contains messages that extend MessageSet.
+
+syntax = "proto2";
+package google.protobuf.internal;
+
+
+// A message with message_set_wire_format.
+message TestMessageSet {
+ option message_set_wire_format = true;
+ extensions 4 to max;
+}
+
+message TestMessageSetExtension1 {
+ extend TestMessageSet {
+ optional TestMessageSetExtension1 message_set_extension = 98418603;
+ }
+ optional int32 i = 15;
+}
+
+message TestMessageSetExtension2 {
+ extend TestMessageSet {
+ optional TestMessageSetExtension2 message_set_extension = 98418634;
+ }
+ optional string str = 25;
+}
+
+// This message was used to generate
+// //net/proto2/python/internal/testdata/message_set_message, but is commented
+// out since it must not actually exist in code, to simulate an "unknown"
+// extension.
+// message TestMessageSetUnknownExtension {
+// extend TestMessageSet {
+// optional TestMessageSetUnknownExtension message_set_extension = 56141421;
+// }
+// optional int64 a = 1;
+// }
diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py
index c4c660ec..d99b89be 100755
--- a/python/google/protobuf/internal/message_test.py
+++ b/python/google/protobuf/internal/message_test.py
@@ -43,6 +43,7 @@ abstract interface.
__author__ = 'gps@google.com (Gregory P. Smith)'
+import collections
import copy
import math
import operator
@@ -63,6 +64,7 @@ from google.protobuf import map_unittest_pb2
from google.protobuf import unittest_pb2
from google.protobuf import unittest_proto3_arena_pb2
from google.protobuf.internal import api_implementation
+from google.protobuf.internal import packed_field_test_pb2
from google.protobuf.internal import test_util
from google.protobuf import message
@@ -428,6 +430,31 @@ class MessageTest(unittest.TestCase):
self.assertEqual(message.repeated_nested_message[4].bb, 5)
self.assertEqual(message.repeated_nested_message[5].bb, 6)
+ def testSortingRepeatedCompositeFieldsStable(self, message_module):
+ """Check passing a custom comparator to sort a repeated composite field."""
+ message = message_module.TestAllTypes()
+
+ message.repeated_nested_message.add().bb = 21
+ message.repeated_nested_message.add().bb = 20
+ message.repeated_nested_message.add().bb = 13
+ message.repeated_nested_message.add().bb = 33
+ message.repeated_nested_message.add().bb = 11
+ message.repeated_nested_message.add().bb = 24
+ message.repeated_nested_message.add().bb = 10
+ message.repeated_nested_message.sort(key=lambda z: z.bb // 10)
+ self.assertEquals(
+ [13, 11, 10, 21, 20, 24, 33],
+ [n.bb for n in message.repeated_nested_message])
+
+ # Make sure that for the C++ implementation, the underlying fields
+ # are actually reordered.
+ pb = message.SerializeToString()
+ message.Clear()
+ message.MergeFromString(pb)
+ self.assertEquals(
+ [13, 11, 10, 21, 20, 24, 33],
+ [n.bb for n in message.repeated_nested_message])
+
def testRepeatedCompositeFieldSortArguments(self, message_module):
"""Check sorting a repeated composite field using list.sort() arguments."""
message = message_module.TestAllTypes()
@@ -521,6 +548,12 @@ class MessageTest(unittest.TestCase):
# TODO(anuraag): Implement extensiondict comparison in C++ and then add test
+ def testRepeatedFieldsAreSequences(self, message_module):
+ m = message_module.TestAllTypes()
+ self.assertIsInstance(m.repeated_int32, collections.MutableSequence)
+ self.assertIsInstance(m.repeated_nested_message,
+ collections.MutableSequence)
+
def ensureNestedMessageExists(self, msg, attribute):
"""Make sure that a nested message object exists.
@@ -563,6 +596,18 @@ class MessageTest(unittest.TestCase):
self.assertFalse(m.HasField('oneof_uint32'))
self.assertTrue(m.HasField('oneof_string'))
+ # Read nested message accessor without accessing submessage.
+ m.oneof_nested_message
+ self.assertEqual('oneof_string', m.WhichOneof('oneof_field'))
+ self.assertTrue(m.HasField('oneof_string'))
+ self.assertFalse(m.HasField('oneof_nested_message'))
+
+ # Read accessor of nested message without accessing submessage.
+ m.oneof_nested_message.bb
+ self.assertEqual('oneof_string', m.WhichOneof('oneof_field'))
+ self.assertTrue(m.HasField('oneof_string'))
+ self.assertFalse(m.HasField('oneof_nested_message'))
+
m.oneof_nested_message.bb = 11
self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field'))
self.assertFalse(m.HasField('oneof_string'))
@@ -1587,6 +1632,21 @@ class Proto3Test(unittest.TestCase):
del msg.map_int32_int32[4]
self.assertEqual(0, len(msg.map_int32_int32))
+ def testMapsAreMapping(self):
+ msg = map_unittest_pb2.TestMap()
+ self.assertIsInstance(msg.map_int32_int32, collections.Mapping)
+ self.assertIsInstance(msg.map_int32_int32, collections.MutableMapping)
+ self.assertIsInstance(msg.map_int32_foreign_message, collections.Mapping)
+ self.assertIsInstance(msg.map_int32_foreign_message,
+ collections.MutableMapping)
+
+ def testMapFindInitializationErrorsSmokeTest(self):
+ msg = map_unittest_pb2.TestMap()
+ msg.map_string_string['abc'] = '123'
+ msg.map_int32_int32[35] = 64
+ msg.map_string_foreign_message['foo'].c = 5
+ self.assertEqual(0, len(msg.FindInitializationErrors()))
+
class ValidTypeNamesTest(unittest.TestCase):
@@ -1610,6 +1670,61 @@ class ValidTypeNamesTest(unittest.TestCase):
self.assertImportFromName(pb.repeated_int32, 'Scalar')
self.assertImportFromName(pb.repeated_nested_message, 'Composite')
+class PackedFieldTest(unittest.TestCase):
+
+ def setMessage(self, message):
+ message.repeated_int32.append(1)
+ message.repeated_int64.append(1)
+ message.repeated_uint32.append(1)
+ message.repeated_uint64.append(1)
+ message.repeated_sint32.append(1)
+ message.repeated_sint64.append(1)
+ message.repeated_fixed32.append(1)
+ message.repeated_fixed64.append(1)
+ message.repeated_sfixed32.append(1)
+ message.repeated_sfixed64.append(1)
+ message.repeated_float.append(1.0)
+ message.repeated_double.append(1.0)
+ message.repeated_bool.append(True)
+ message.repeated_nested_enum.append(1)
+
+ def testPackedFields(self):
+ message = packed_field_test_pb2.TestPackedTypes()
+ self.setMessage(message)
+ golden_data = (b'\x0A\x01\x01'
+ b'\x12\x01\x01'
+ b'\x1A\x01\x01'
+ b'\x22\x01\x01'
+ b'\x2A\x01\x02'
+ b'\x32\x01\x02'
+ b'\x3A\x04\x01\x00\x00\x00'
+ b'\x42\x08\x01\x00\x00\x00\x00\x00\x00\x00'
+ b'\x4A\x04\x01\x00\x00\x00'
+ b'\x52\x08\x01\x00\x00\x00\x00\x00\x00\x00'
+ b'\x5A\x04\x00\x00\x80\x3f'
+ b'\x62\x08\x00\x00\x00\x00\x00\x00\xf0\x3f'
+ b'\x6A\x01\x01'
+ b'\x72\x01\x01')
+ self.assertEqual(golden_data, message.SerializeToString())
+
+ def testUnpackedFields(self):
+ message = packed_field_test_pb2.TestUnpackedTypes()
+ self.setMessage(message)
+ golden_data = (b'\x08\x01'
+ b'\x10\x01'
+ b'\x18\x01'
+ b'\x20\x01'
+ b'\x28\x02'
+ b'\x30\x02'
+ b'\x3D\x01\x00\x00\x00'
+ b'\x41\x01\x00\x00\x00\x00\x00\x00\x00'
+ b'\x4D\x01\x00\x00\x00'
+ b'\x51\x01\x00\x00\x00\x00\x00\x00\x00'
+ b'\x5D\x00\x00\x80\x3f'
+ b'\x61\x00\x00\x00\x00\x00\x00\xf0\x3f'
+ b'\x68\x01'
+ b'\x70\x01')
+ self.assertEqual(golden_data, message.SerializeToString())
if __name__ == '__main__':
unittest.main()
diff --git a/python/google/protobuf/internal/packed_field_test.proto b/python/google/protobuf/internal/packed_field_test.proto
new file mode 100644
index 00000000..0dfdc10a
--- /dev/null
+++ b/python/google/protobuf/internal/packed_field_test.proto
@@ -0,0 +1,73 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf.python.internal;
+
+message TestPackedTypes {
+ enum NestedEnum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ }
+
+ repeated int32 repeated_int32 = 1;
+ repeated int64 repeated_int64 = 2;
+ repeated uint32 repeated_uint32 = 3;
+ repeated uint64 repeated_uint64 = 4;
+ repeated sint32 repeated_sint32 = 5;
+ repeated sint64 repeated_sint64 = 6;
+ repeated fixed32 repeated_fixed32 = 7;
+ repeated fixed64 repeated_fixed64 = 8;
+ repeated sfixed32 repeated_sfixed32 = 9;
+ repeated sfixed64 repeated_sfixed64 = 10;
+ repeated float repeated_float = 11;
+ repeated double repeated_double = 12;
+ repeated bool repeated_bool = 13;
+ repeated NestedEnum repeated_nested_enum = 14;
+}
+
+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 TestPackedTypes.NestedEnum repeated_nested_enum = 14 [packed = false];
+}
diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py
index 9a72315e..4e5032a7 100755
--- a/python/google/protobuf/internal/python_message.py
+++ b/python/google/protobuf/internal/python_message.py
@@ -76,34 +76,108 @@ from google.protobuf import text_format
_FieldDescriptor = descriptor_mod.FieldDescriptor
-def NewMessage(bases, descriptor, dictionary):
- _AddClassAttributesForNestedExtensions(descriptor, dictionary)
- _AddSlots(descriptor, dictionary)
- return bases
-
-
-def InitMessage(descriptor, cls):
- cls._decoders_by_tag = {}
- cls._extensions_by_name = {}
- cls._extensions_by_number = {}
- if (descriptor.has_options and
- descriptor.GetOptions().message_set_wire_format):
- cls._decoders_by_tag[decoder.MESSAGE_SET_ITEM_TAG] = (
- decoder.MessageSetItemDecoder(cls._extensions_by_number), None)
-
- # Attach stuff to each FieldDescriptor for quick lookup later on.
- for field in descriptor.fields:
- _AttachFieldHelpers(cls, field)
+class GeneratedProtocolMessageType(type):
+
+ """Metaclass for protocol message classes created at runtime from Descriptors.
+
+ We add implementations for all methods described in the Message class. We
+ also create properties to allow getting/setting all fields in the protocol
+ message. Finally, we create slots to prevent users from accidentally
+ "setting" nonexistent fields in the protocol message, which then wouldn't get
+ serialized / deserialized properly.
+
+ The protocol compiler currently uses this metaclass to create protocol
+ message classes at runtime. Clients can also manually create their own
+ classes at runtime, as in this example:
+
+ mydescriptor = Descriptor(.....)
+ class MyProtoClass(Message):
+ __metaclass__ = GeneratedProtocolMessageType
+ DESCRIPTOR = mydescriptor
+ myproto_instance = MyProtoClass()
+ myproto.foo_field = 23
+ ...
+
+ The above example will not work for nested types. If you wish to include them,
+ use reflection.MakeClass() instead of manually instantiating the class in
+ order to create the appropriate class structure.
+ """
+
+ # Must be consistent with the protocol-compiler code in
+ # proto2/compiler/internal/generator.*.
+ _DESCRIPTOR_KEY = 'DESCRIPTOR'
+
+ def __new__(cls, name, bases, dictionary):
+ """Custom allocation for runtime-generated class types.
+
+ We override __new__ because this is apparently the only place
+ where we can meaningfully set __slots__ on the class we're creating(?).
+ (The interplay between metaclasses and slots is not very well-documented).
+
+ Args:
+ name: Name of the class (ignored, but required by the
+ metaclass protocol).
+ bases: Base classes of the class we're constructing.
+ (Should be message.Message). We ignore this field, but
+ it's required by the metaclass protocol
+ dictionary: The class dictionary of the class we're
+ constructing. dictionary[_DESCRIPTOR_KEY] must contain
+ a Descriptor object describing this protocol message
+ type.
+
+ Returns:
+ Newly-allocated class.
+ """
+ descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
+ _AddClassAttributesForNestedExtensions(descriptor, dictionary)
+ _AddSlots(descriptor, dictionary)
+
+ superclass = super(GeneratedProtocolMessageType, cls)
+ new_class = superclass.__new__(cls, name, bases, dictionary)
+ return new_class
+
+ def __init__(cls, name, bases, dictionary):
+ """Here we perform the majority of our work on the class.
+ We add enum getters, an __init__ method, implementations
+ of all Message methods, and properties for all fields
+ in the protocol type.
- descriptor._concrete_class = cls # pylint: disable=protected-access
- _AddEnumValues(descriptor, cls)
- _AddInitMethod(descriptor, cls)
- _AddPropertiesForFields(descriptor, cls)
- _AddPropertiesForExtensions(descriptor, cls)
- _AddStaticMethods(cls)
- _AddMessageMethods(descriptor, cls)
- _AddPrivateHelperMethods(descriptor, cls)
- copyreg.pickle(cls, lambda obj: (cls, (), obj.__getstate__()))
+ Args:
+ name: Name of the class (ignored, but required by the
+ metaclass protocol).
+ bases: Base classes of the class we're constructing.
+ (Should be message.Message). We ignore this field, but
+ it's required by the metaclass protocol
+ dictionary: The class dictionary of the class we're
+ constructing. dictionary[_DESCRIPTOR_KEY] must contain
+ a Descriptor object describing this protocol message
+ type.
+ """
+ descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
+ cls._decoders_by_tag = {}
+ cls._extensions_by_name = {}
+ cls._extensions_by_number = {}
+ if (descriptor.has_options and
+ descriptor.GetOptions().message_set_wire_format):
+ cls._decoders_by_tag[decoder.MESSAGE_SET_ITEM_TAG] = (
+ decoder.MessageSetItemDecoder(cls._extensions_by_number), None)
+
+ # Attach stuff to each FieldDescriptor for quick lookup later on.
+ for field in descriptor.fields:
+ _AttachFieldHelpers(cls, field)
+
+ descriptor._concrete_class = cls # pylint: disable=protected-access
+ _AddEnumValues(descriptor, cls)
+ _AddInitMethod(descriptor, cls)
+ _AddPropertiesForFields(descriptor, cls)
+ _AddPropertiesForExtensions(descriptor, cls)
+ _AddStaticMethods(cls)
+ _AddMessageMethods(descriptor, cls)
+ _AddPrivateHelperMethods(descriptor, cls)
+ copyreg.pickle(cls, lambda obj: (cls, (), obj.__getstate__()))
+
+ superclass = super(GeneratedProtocolMessageType, cls)
+ superclass.__init__(name, bases, dictionary)
# Stateless helpers for GeneratedProtocolMessageType below.
@@ -353,9 +427,10 @@ def _DefaultValueConstructorForField(field):
message_type = field.message_type
def MakeSubMessageDefault(message):
result = message_type._concrete_class()
- result._SetListener(message._listener_for_children)
- if field.containing_oneof:
- message._UpdateOneofState(field)
+ result._SetListener(
+ _OneofListener(message, field)
+ if field.containing_oneof is not None
+ else message._listener_for_children)
return result
return MakeSubMessageDefault
@@ -625,21 +700,11 @@ def _AddPropertiesForNonRepeatedCompositeField(field, cls):
proto_field_name = field.name
property_name = _PropertyName(proto_field_name)
- # TODO(komarek): Can anyone explain to me why we cache the message_type this
- # way, instead of referring to field.message_type inside of getter(self)?
- # What if someone sets message_type later on (which makes for simpler
- # dyanmic proto descriptor and class creation code).
- message_type = field.message_type
-
def getter(self):
field_value = self._fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
- field_value = message_type._concrete_class() # use field.message_type?
- field_value._SetListener(
- _OneofListener(self, field)
- if field.containing_oneof is not None
- else self._listener_for_children)
+ field_value = field._default_constructor(self)
# Atomically check if another thread has preempted us and, if not, swap
# in the new object we just created. If someone has preempted us, we
@@ -1112,7 +1177,7 @@ def _AddIsInitializedMethod(message_descriptor, cls):
if _IsMessageMapField(field):
for key in value:
element = value[key]
- prefix = "%s[%d]." % (name, key)
+ prefix = "%s[%s]." % (name, key)
sub_errors = element.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
else:
@@ -1164,8 +1229,6 @@ def _AddMergeFromMethod(cls):
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
fields[field] = field_value
- if field.containing_oneof:
- self._UpdateOneofState(field)
field_value.MergeFrom(value)
else:
self._fields[field] = value
diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index 5d691bcf..26611353 100755
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -57,6 +57,7 @@ from google.protobuf import text_format
from google.protobuf.internal import api_implementation
from google.protobuf.internal import more_extensions_pb2
from google.protobuf.internal import more_messages_pb2
+from google.protobuf.internal import message_set_extensions_pb2
from google.protobuf.internal import wire_format
from google.protobuf.internal import test_util
from google.protobuf.internal import decoder
@@ -1689,8 +1690,8 @@ class ReflectionTest(unittest.TestCase):
proto.optional_string = 'abc'
def testStringUTF8Serialization(self):
- proto = unittest_mset_pb2.TestMessageSet()
- extension_message = unittest_mset_pb2.TestMessageSetExtension2
+ proto = message_set_extensions_pb2.TestMessageSet()
+ extension_message = message_set_extensions_pb2.TestMessageSetExtension2
extension = extension_message.message_set_extension
test_utf8 = u'Тест'
@@ -1710,15 +1711,14 @@ class ReflectionTest(unittest.TestCase):
bytes_read = raw.MergeFromString(serialized)
self.assertEqual(len(serialized), bytes_read)
- message2 = unittest_mset_pb2.TestMessageSetExtension2()
+ message2 = message_set_extensions_pb2.TestMessageSetExtension2()
self.assertEqual(1, len(raw.item))
# Check that the type_id is the same as the tag ID in the .proto file.
- self.assertEqual(raw.item[0].type_id, 1547769)
+ self.assertEqual(raw.item[0].type_id, 98418634)
# Check the actual bytes on the wire.
- self.assertTrue(
- raw.item[0].message.endswith(test_utf8_bytes))
+ self.assertTrue(raw.item[0].message.endswith(test_utf8_bytes))
bytes_read = message2.MergeFromString(raw.item[0].message)
self.assertEqual(len(raw.item[0].message), bytes_read)
@@ -2391,9 +2391,9 @@ class SerializationTest(unittest.TestCase):
self.assertEqual(42, second_proto.optional_nested_message.bb)
def testMessageSetWireFormat(self):
- proto = unittest_mset_pb2.TestMessageSet()
- extension_message1 = unittest_mset_pb2.TestMessageSetExtension1
- extension_message2 = unittest_mset_pb2.TestMessageSetExtension2
+ proto = message_set_extensions_pb2.TestMessageSet()
+ extension_message1 = message_set_extensions_pb2.TestMessageSetExtension1
+ extension_message2 = message_set_extensions_pb2.TestMessageSetExtension2
extension1 = extension_message1.message_set_extension
extension2 = extension_message2.message_set_extension
proto.Extensions[extension1].i = 123
@@ -2411,20 +2411,20 @@ class SerializationTest(unittest.TestCase):
raw.MergeFromString(serialized))
self.assertEqual(2, len(raw.item))
- message1 = unittest_mset_pb2.TestMessageSetExtension1()
+ message1 = message_set_extensions_pb2.TestMessageSetExtension1()
self.assertEqual(
len(raw.item[0].message),
message1.MergeFromString(raw.item[0].message))
self.assertEqual(123, message1.i)
- message2 = unittest_mset_pb2.TestMessageSetExtension2()
+ message2 = message_set_extensions_pb2.TestMessageSetExtension2()
self.assertEqual(
len(raw.item[1].message),
message2.MergeFromString(raw.item[1].message))
self.assertEqual('foo', message2.str)
# Deserialize using the MessageSet wire format.
- proto2 = unittest_mset_pb2.TestMessageSet()
+ proto2 = message_set_extensions_pb2.TestMessageSet()
self.assertEqual(
len(serialized),
proto2.MergeFromString(serialized))
@@ -2442,37 +2442,37 @@ class SerializationTest(unittest.TestCase):
# Add an item.
item = raw.item.add()
- item.type_id = 1545008
- extension_message1 = unittest_mset_pb2.TestMessageSetExtension1
- message1 = unittest_mset_pb2.TestMessageSetExtension1()
+ item.type_id = 98418603
+ extension_message1 = message_set_extensions_pb2.TestMessageSetExtension1
+ message1 = message_set_extensions_pb2.TestMessageSetExtension1()
message1.i = 12345
item.message = message1.SerializeToString()
# Add a second, unknown extension.
item = raw.item.add()
- item.type_id = 1545009
- extension_message1 = unittest_mset_pb2.TestMessageSetExtension1
- message1 = unittest_mset_pb2.TestMessageSetExtension1()
+ item.type_id = 98418604
+ extension_message1 = message_set_extensions_pb2.TestMessageSetExtension1
+ message1 = message_set_extensions_pb2.TestMessageSetExtension1()
message1.i = 12346
item.message = message1.SerializeToString()
# Add another unknown extension.
item = raw.item.add()
- item.type_id = 1545010
- message1 = unittest_mset_pb2.TestMessageSetExtension2()
+ item.type_id = 98418605
+ message1 = message_set_extensions_pb2.TestMessageSetExtension2()
message1.str = 'foo'
item.message = message1.SerializeToString()
serialized = raw.SerializeToString()
# Parse message using the message set wire format.
- proto = unittest_mset_pb2.TestMessageSet()
+ proto = message_set_extensions_pb2.TestMessageSet()
self.assertEqual(
len(serialized),
proto.MergeFromString(serialized))
# Check that the message parsed well.
- extension_message1 = unittest_mset_pb2.TestMessageSetExtension1
+ extension_message1 = message_set_extensions_pb2.TestMessageSetExtension1
extension1 = extension_message1.message_set_extension
self.assertEqual(12345, proto.Extensions[extension1].i)
@@ -2801,7 +2801,7 @@ class SerializationTest(unittest.TestCase):
class OptionsTest(unittest.TestCase):
def testMessageOptions(self):
- proto = unittest_mset_pb2.TestMessageSet()
+ proto = message_set_extensions_pb2.TestMessageSet()
self.assertEqual(True,
proto.DESCRIPTOR.GetOptions().message_set_wire_format)
proto = unittest_pb2.TestAllTypes()
@@ -2820,7 +2820,7 @@ class OptionsTest(unittest.TestCase):
proto.packed_double.append(3.0)
for field_descriptor, _ in proto.ListFields():
self.assertEqual(True, field_descriptor.GetOptions().packed)
- self.assertEqual(reflection._FieldDescriptor.LABEL_REPEATED,
+ self.assertEqual(descriptor.FieldDescriptor.LABEL_REPEATED,
field_descriptor.label)
@@ -2910,6 +2910,13 @@ class ClassAPITest(unittest.TestCase):
def testParsingFlatClassWithExplicitClassDeclaration(self):
"""Test that the generated class can parse a flat message."""
+ # TODO(xiaofeng): This test fails with cpp implemetnation in the call
+ # of six.with_metaclass(). The other two callsites of with_metaclass
+ # in this file are both excluded from cpp test, so it might be expected
+ # to fail. Need someone more familiar with the python code to take a
+ # look at this.
+ if api_implementation.Type() != 'python':
+ return
file_descriptor = descriptor_pb2.FileDescriptorProto()
file_descriptor.ParseFromString(self._GetSerializedFileDescriptor('A'))
msg_descriptor = descriptor.MakeDescriptor(
diff --git a/python/google/protobuf/internal/test_util.py b/python/google/protobuf/internal/test_util.py
index fec65382..ac88fa81 100755
--- a/python/google/protobuf/internal/test_util.py
+++ b/python/google/protobuf/internal/test_util.py
@@ -604,7 +604,8 @@ def GoldenFile(filename):
# Search internally.
path = '.'
- full_path = os.path.join(path, 'third_party/py/google/protobuf/testdata', filename)
+ full_path = os.path.join(path, 'third_party/py/google/protobuf/testdata',
+ filename)
if os.path.exists(full_path):
# Found it. Load the golden file from the testdata directory.
return open(full_path, 'rb')
diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index 67d08dfe..d332b77d 100755
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -35,8 +35,8 @@
__author__ = 'kenton@google.com (Kenton Varda)'
import re
-
import six
+import string
try:
import unittest2 as unittest
@@ -501,6 +501,36 @@ class OnlyWorksWithProto2RightNowTests(TextFormatBase):
' }\n'
'}\n')
+ def testMapOrderEnforcement(self):
+ message = map_unittest_pb2.TestMap()
+ for letter in string.ascii_uppercase[13:26]:
+ message.map_string_string[letter] = 'dummy'
+ for letter in reversed(string.ascii_uppercase[0:13]):
+ message.map_string_string[letter] = 'dummy'
+ golden = ''.join((
+ 'map_string_string {\n key: "%c"\n value: "dummy"\n}\n' % (letter,)
+ for letter in string.ascii_uppercase))
+ self.CompareToGoldenText(text_format.MessageToString(message), golden)
+
+ def testMapOrderSemantics(self):
+ golden_lines = self.ReadGolden('map_test_data.txt')
+ # The C++ implementation emits defaulted-value fields, while the Python
+ # implementation does not. Adjusting for this is awkward, but it is
+ # valuable to test against a common golden file.
+ line_blacklist = (' key: 0\n',
+ ' value: 0\n',
+ ' key: false\n',
+ ' value: false\n')
+ golden_lines = [line for line in golden_lines if line not in line_blacklist]
+
+ message = map_unittest_pb2.TestMap()
+ text_format.ParseLines(golden_lines, message)
+ candidate = text_format.MessageToString(message)
+ # The Python implementation emits "1.0" for the double value that the C++
+ # implementation emits as "1".
+ candidate = candidate.replace('1.0', '1', 2)
+ self.assertMultiLineEqual(candidate, ''.join(golden_lines))
+
# Tests of proto2-only features (MessageSet, extensions, etc.).
class Proto2Tests(TextFormatBase):
diff --git a/python/google/protobuf/internal/unknown_fields_test.py b/python/google/protobuf/internal/unknown_fields_test.py
index 1b5d7bc0..011d3b55 100755
--- a/python/google/protobuf/internal/unknown_fields_test.py
+++ b/python/google/protobuf/internal/unknown_fields_test.py
@@ -45,11 +45,18 @@ 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 encoder
+from google.protobuf.internal import message_set_extensions_pb2
from google.protobuf.internal import missing_enum_values_pb2
from google.protobuf.internal import test_util
from google.protobuf.internal import type_checkers
+def SkipIfCppImplementation(func):
+ return unittest.skipIf(
+ api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
+ 'C++ implementation does not expose unknown fields to Python')(func)
+
+
class UnknownFieldsTest(unittest.TestCase):
def setUp(self):
@@ -87,15 +94,15 @@ class UnknownFieldsTest(unittest.TestCase):
# Add an unknown extension.
item = raw.item.add()
- item.type_id = 1545009
- message1 = unittest_mset_pb2.TestMessageSetExtension1()
+ item.type_id = 98418603
+ message1 = message_set_extensions_pb2.TestMessageSetExtension1()
message1.i = 12345
item.message = message1.SerializeToString()
serialized = raw.SerializeToString()
# Parse message using the message set wire format.
- proto = unittest_mset_pb2.TestMessageSet()
+ proto = message_set_extensions_pb2.TestMessageSet()
proto.MergeFromString(serialized)
# Verify that the unknown extension is serialized unchanged
@@ -104,13 +111,6 @@ class UnknownFieldsTest(unittest.TestCase):
new_raw.MergeFromString(reserialized)
self.assertEqual(raw, new_raw)
- # C++ implementation for proto2 does not currently take into account unknown
- # fields when checking equality.
- #
- # TODO(haberman): fix this.
- @unittest.skipIf(
- api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
- 'C++ implementation does not expose unknown fields to Python')
def testEquals(self):
message = unittest_pb2.TestEmptyMessage()
message.ParseFromString(self.all_fields_data)
@@ -121,9 +121,6 @@ class UnknownFieldsTest(unittest.TestCase):
self.assertNotEqual(self.empty_message, message)
-@unittest.skipIf(
- api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
- 'C++ implementation does not expose unknown fields to Python')
class UnknownFieldsAccessorsTest(unittest.TestCase):
def setUp(self):
@@ -133,7 +130,14 @@ class UnknownFieldsAccessorsTest(unittest.TestCase):
self.all_fields_data = self.all_fields.SerializeToString()
self.empty_message = unittest_pb2.TestEmptyMessage()
self.empty_message.ParseFromString(self.all_fields_data)
- self.unknown_fields = self.empty_message._unknown_fields
+ if api_implementation.Type() != 'cpp':
+ # _unknown_fields is an implementation detail.
+ self.unknown_fields = self.empty_message._unknown_fields
+
+ # All the tests that use GetField() check an implementation detail of the
+ # Python implementation, which stores unknown fields as serialized strings.
+ # These tests are skipped by the C++ implementation: it's enough to check that
+ # the message is correctly serialized.
def GetField(self, name):
field_descriptor = self.descriptor.fields_by_name[name]
@@ -146,30 +150,37 @@ class UnknownFieldsAccessorsTest(unittest.TestCase):
decoder(value, 0, len(value), self.all_fields, result_dict)
return result_dict[field_descriptor]
+ @SkipIfCppImplementation
def testEnum(self):
value = self.GetField('optional_nested_enum')
self.assertEqual(self.all_fields.optional_nested_enum, value)
+ @SkipIfCppImplementation
def testRepeatedEnum(self):
value = self.GetField('repeated_nested_enum')
self.assertEqual(self.all_fields.repeated_nested_enum, value)
+ @SkipIfCppImplementation
def testVarint(self):
value = self.GetField('optional_int32')
self.assertEqual(self.all_fields.optional_int32, value)
+ @SkipIfCppImplementation
def testFixed32(self):
value = self.GetField('optional_fixed32')
self.assertEqual(self.all_fields.optional_fixed32, value)
+ @SkipIfCppImplementation
def testFixed64(self):
value = self.GetField('optional_fixed64')
self.assertEqual(self.all_fields.optional_fixed64, value)
+ @SkipIfCppImplementation
def testLengthDelimited(self):
value = self.GetField('optional_string')
self.assertEqual(self.all_fields.optional_string, value)
+ @SkipIfCppImplementation
def testGroup(self):
value = self.GetField('optionalgroup')
self.assertEqual(self.all_fields.optionalgroup, value)
@@ -177,7 +188,7 @@ class UnknownFieldsAccessorsTest(unittest.TestCase):
def testCopyFrom(self):
message = unittest_pb2.TestEmptyMessage()
message.CopyFrom(self.empty_message)
- self.assertEqual(self.unknown_fields, message._unknown_fields)
+ self.assertEqual(message.SerializeToString(), self.all_fields_data)
def testMergeFrom(self):
message = unittest_pb2.TestAllTypes()
@@ -191,27 +202,26 @@ class UnknownFieldsAccessorsTest(unittest.TestCase):
message.optional_uint32 = 4
destination = unittest_pb2.TestEmptyMessage()
destination.ParseFromString(message.SerializeToString())
- unknown_fields = destination._unknown_fields[:]
destination.MergeFrom(source)
- self.assertEqual(unknown_fields + source._unknown_fields,
- destination._unknown_fields)
+ # Check that the fields where correctly merged, even stored in the unknown
+ # fields set.
+ message.ParseFromString(destination.SerializeToString())
+ self.assertEqual(message.optional_int32, 1)
+ self.assertEqual(message.optional_uint32, 2)
+ self.assertEqual(message.optional_int64, 3)
def testClear(self):
self.empty_message.Clear()
- self.assertEqual(0, len(self.empty_message._unknown_fields))
+ # All cleared, even unknown fields.
+ self.assertEqual(self.empty_message.SerializeToString(), b'')
def testUnknownExtensions(self):
message = unittest_pb2.TestEmptyMessageWithExtensions()
message.ParseFromString(self.all_fields_data)
- self.assertEqual(self.empty_message._unknown_fields,
- message._unknown_fields)
-
+ self.assertEqual(message.SerializeToString(), self.all_fields_data)
-@unittest.skipIf(
- api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
- 'C++ implementation does not expose unknown fields to Python')
class UnknownEnumValuesTest(unittest.TestCase):
def setUp(self):
@@ -231,7 +241,14 @@ class UnknownEnumValuesTest(unittest.TestCase):
self.message_data = self.message.SerializeToString()
self.missing_message = missing_enum_values_pb2.TestMissingEnumValues()
self.missing_message.ParseFromString(self.message_data)
- self.unknown_fields = self.missing_message._unknown_fields
+ if api_implementation.Type() != 'cpp':
+ # _unknown_fields is an implementation detail.
+ self.unknown_fields = self.missing_message._unknown_fields
+
+ # All the tests that use GetField() check an implementation detail of the
+ # Python implementation, which stores unknown fields as serialized strings.
+ # These tests are skipped by the C++ implementation: it's enough to check that
+ # the message is correctly serialized.
def GetField(self, name):
field_descriptor = self.descriptor.fields_by_name[name]
@@ -245,15 +262,18 @@ class UnknownEnumValuesTest(unittest.TestCase):
decoder(value, 0, len(value), self.message, result_dict)
return result_dict[field_descriptor]
+ @SkipIfCppImplementation
def testUnknownEnumValue(self):
self.assertFalse(self.missing_message.HasField('optional_nested_enum'))
value = self.GetField('optional_nested_enum')
self.assertEqual(self.message.optional_nested_enum, value)
+ @SkipIfCppImplementation
def testUnknownRepeatedEnumValue(self):
value = self.GetField('repeated_nested_enum')
self.assertEqual(self.message.repeated_nested_enum, value)
+ @SkipIfCppImplementation
def testUnknownPackedEnumValue(self):
value = self.GetField('packed_nested_enum')
self.assertEqual(self.message.packed_nested_enum, value)
diff --git a/python/google/protobuf/pyext/cpp_message.py b/python/google/protobuf/pyext/cpp_message.py
index 037bb72c..b215211e 100644
--- a/python/google/protobuf/pyext/cpp_message.py
+++ b/python/google/protobuf/pyext/cpp_message.py
@@ -37,21 +37,29 @@ Descriptor objects at runtime backed by the protocol buffer C++ API.
__author__ = 'tibell@google.com (Johan Tibell)'
from google.protobuf.pyext import _message
-from google.protobuf import message
-def NewMessage(bases, message_descriptor, dictionary):
- """Creates a new protocol message *class*."""
- new_bases = []
- for base in bases:
- if base is message.Message:
- # _message.Message must come before message.Message as it
- # overrides methods in that class.
- new_bases.append(_message.Message)
- new_bases.append(base)
- return tuple(new_bases)
+class GeneratedProtocolMessageType(_message.MessageMeta):
+ """Metaclass for protocol message classes created at runtime from Descriptors.
-def InitMessage(message_descriptor, cls):
- """Finalizes the creation of a message class."""
- cls.AddDescriptors(message_descriptor)
+ The protocol compiler currently uses this metaclass to create protocol
+ message classes at runtime. Clients can also manually create their own
+ classes at runtime, as in this example:
+
+ mydescriptor = Descriptor(.....)
+ class MyProtoClass(Message):
+ __metaclass__ = GeneratedProtocolMessageType
+ DESCRIPTOR = mydescriptor
+ myproto_instance = MyProtoClass()
+ myproto.foo_field = 23
+ ...
+
+ The above example will not work for nested types. If you wish to include them,
+ use reflection.MakeClass() instead of manually instantiating the class in
+ order to create the appropriate class structure.
+ """
+
+ # Must be consistent with the protocol-compiler code in
+ # proto2/compiler/internal/generator.*.
+ _DESCRIPTOR_KEY = 'DESCRIPTOR'
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc
index 2160757b..3806643f 100644
--- a/python/google/protobuf/pyext/descriptor.cc
+++ b/python/google/protobuf/pyext/descriptor.cc
@@ -62,6 +62,14 @@ namespace google {
namespace protobuf {
namespace python {
+// Store interned descriptors, so that the same C++ descriptor yields the same
+// Python object. Objects are not immortal: this map does not own the
+// references, and items are deleted when the last reference to the object is
+// released.
+// This is enough to support the "is" operator on live objects.
+// All descriptors are stored here.
+hash_map<const void*, PyObject*> interned_descriptors;
+
PyObject* PyString_FromCppString(const string& str) {
return PyString_FromStringAndSize(str.c_str(), str.size());
}
@@ -147,6 +155,24 @@ static int CheckCalledFromGeneratedFile(const char* attr_name) {
// Helper functions for descriptor objects.
+// A set of templates to retrieve the C++ FileDescriptor of any descriptor.
+template<class DescriptorClass>
+const FileDescriptor* GetFileDescriptor(const DescriptorClass* descriptor) {
+ return descriptor->file();
+}
+template<>
+const FileDescriptor* GetFileDescriptor(const FileDescriptor* descriptor) {
+ return descriptor;
+}
+template<>
+const FileDescriptor* GetFileDescriptor(const EnumValueDescriptor* descriptor) {
+ return descriptor->type()->file();
+}
+template<>
+const FileDescriptor* GetFileDescriptor(const OneofDescriptor* descriptor) {
+ return descriptor->containing_type()->file();
+}
+
// Converts options into a Python protobuf, and cache the result.
//
// This is a bit tricky because options can contain extension fields defined in
@@ -156,8 +182,13 @@ static int CheckCalledFromGeneratedFile(const char* attr_name) {
// Always returns a new reference.
template<class DescriptorClass>
static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
+ // Options (and their extensions) are completely resolved in the proto file
+ // containing the descriptor.
+ PyDescriptorPool* pool = GetDescriptorPool_FromPool(
+ GetFileDescriptor(descriptor)->pool());
+
hash_map<const void*, PyObject*>* descriptor_options =
- GetDescriptorPool()->descriptor_options;
+ pool->descriptor_options;
// First search in the cache.
if (descriptor_options->find(descriptor) != descriptor_options->end()) {
PyObject *value = (*descriptor_options)[descriptor];
@@ -170,7 +201,7 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
const Message& options(descriptor->options());
const Descriptor *message_type = options.GetDescriptor();
PyObject* message_class(cdescriptor_pool::GetMessageClass(
- GetDescriptorPool(), message_type));
+ pool, message_type));
if (message_class == NULL) {
PyErr_Format(PyExc_TypeError, "Could not retrieve class for Options: %s",
message_type->full_name().c_str());
@@ -192,8 +223,8 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
options.SerializeToString(&serialized);
io::CodedInputStream input(
reinterpret_cast<const uint8*>(serialized.c_str()), serialized.size());
- input.SetExtensionRegistry(GetDescriptorPool()->pool,
- cmessage::GetMessageFactory());
+ input.SetExtensionRegistry(pool->pool,
+ GetDescriptorPool()->message_factory);
bool success = cmsg->message->MergePartialFromCodedStream(&input);
if (!success) {
PyErr_Format(PyExc_ValueError, "Error parsing Options message");
@@ -203,7 +234,7 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
// Cache the result.
Py_INCREF(value);
- (*GetDescriptorPool()->descriptor_options)[descriptor] = value.get();
+ (*pool->descriptor_options)[descriptor] = value.get();
return value.release();
}
@@ -237,6 +268,9 @@ typedef struct PyBaseDescriptor {
// Pointer to the C++ proto2 descriptor.
// Like all descriptors, it is owned by the global DescriptorPool.
const void* descriptor;
+
+ // Owned reference to the DescriptorPool, to ensure it is kept alive.
+ PyDescriptorPool* pool;
} PyBaseDescriptor;
@@ -258,7 +292,9 @@ namespace descriptor {
// 'was_created' is an optional pointer to a bool, and is set to true if a new
// object was allocated.
// Always return a new reference.
-PyObject* NewInternedDescriptor(PyTypeObject* type, const void* descriptor,
+template<class DescriptorClass>
+PyObject* NewInternedDescriptor(PyTypeObject* type,
+ const DescriptorClass* descriptor,
bool* was_created) {
if (was_created) {
*was_created = false;
@@ -270,8 +306,8 @@ PyObject* NewInternedDescriptor(PyTypeObject* type, const void* descriptor,
// See if the object is in the map of interned descriptors
hash_map<const void*, PyObject*>::iterator it =
- GetDescriptorPool()->interned_descriptors->find(descriptor);
- if (it != GetDescriptorPool()->interned_descriptors->end()) {
+ interned_descriptors.find(descriptor);
+ if (it != interned_descriptors.end()) {
GOOGLE_DCHECK(Py_TYPE(it->second) == type);
Py_INCREF(it->second);
return it->second;
@@ -283,10 +319,21 @@ PyObject* NewInternedDescriptor(PyTypeObject* type, const void* descriptor,
return NULL;
}
py_descriptor->descriptor = descriptor;
+
// and cache it.
- GetDescriptorPool()->interned_descriptors->insert(
+ interned_descriptors.insert(
std::make_pair(descriptor, reinterpret_cast<PyObject*>(py_descriptor)));
+ // Ensures that the DescriptorPool stays alive.
+ PyDescriptorPool* pool = GetDescriptorPool_FromPool(
+ GetFileDescriptor(descriptor)->pool());
+ if (pool == NULL) {
+ Py_DECREF(py_descriptor);
+ return NULL;
+ }
+ Py_INCREF(pool);
+ py_descriptor->pool = pool;
+
if (was_created) {
*was_created = true;
}
@@ -295,7 +342,8 @@ PyObject* NewInternedDescriptor(PyTypeObject* type, const void* descriptor,
static void Dealloc(PyBaseDescriptor* self) {
// Remove from interned dictionary
- GetDescriptorPool()->interned_descriptors->erase(self->descriptor);
+ interned_descriptors.erase(self->descriptor);
+ Py_CLEAR(self->pool);
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
}
diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc
index ecd90847..7aed651d 100644
--- a/python/google/protobuf/pyext/descriptor_pool.cc
+++ b/python/google/protobuf/pyext/descriptor_pool.cc
@@ -33,6 +33,7 @@
#include <Python.h>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/pyext/descriptor_pool.h>
#include <google/protobuf/pyext/descriptor.h>
#include <google/protobuf/pyext/message.h>
@@ -53,9 +54,13 @@ namespace google {
namespace protobuf {
namespace python {
+// A map to cache Python Pools per C++ pointer.
+// Pointers are not owned here, and belong to the PyDescriptorPool.
+static hash_map<const DescriptorPool*, PyDescriptorPool*> descriptor_pool_map;
+
namespace cdescriptor_pool {
-PyDescriptorPool* NewDescriptorPool() {
+static PyDescriptorPool* NewDescriptorPool() {
PyDescriptorPool* cdescriptor_pool = PyObject_New(
PyDescriptorPool, &PyDescriptorPool_Type);
if (cdescriptor_pool == NULL) {
@@ -67,32 +72,43 @@ PyDescriptorPool* NewDescriptorPool() {
// as underlay.
cdescriptor_pool->pool = new DescriptorPool(DescriptorPool::generated_pool());
+ DynamicMessageFactory* message_factory = new DynamicMessageFactory();
+ // This option might be the default some day.
+ message_factory->SetDelegateToGeneratedFactory(true);
+ cdescriptor_pool->message_factory = message_factory;
+
// TODO(amauryfa): Rewrite the SymbolDatabase in C so that it uses the same
// storage.
cdescriptor_pool->classes_by_descriptor =
new PyDescriptorPool::ClassesByMessageMap();
- cdescriptor_pool->interned_descriptors =
- new hash_map<const void*, PyObject *>();
cdescriptor_pool->descriptor_options =
new hash_map<const void*, PyObject *>();
+ if (!descriptor_pool_map.insert(
+ std::make_pair(cdescriptor_pool->pool, cdescriptor_pool)).second) {
+ // Should never happen -- would indicate an internal error / bug.
+ PyErr_SetString(PyExc_ValueError, "DescriptorPool already registered");
+ return NULL;
+ }
+
return cdescriptor_pool;
}
static void Dealloc(PyDescriptorPool* self) {
typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
+ descriptor_pool_map.erase(self->pool);
for (iterator it = self->classes_by_descriptor->begin();
it != self->classes_by_descriptor->end(); ++it) {
Py_DECREF(it->second);
}
delete self->classes_by_descriptor;
- delete self->interned_descriptors; // its references were borrowed.
for (hash_map<const void*, PyObject*>::iterator it =
self->descriptor_options->begin();
it != self->descriptor_options->end(); ++it) {
Py_DECREF(it->second);
}
delete self->descriptor_options;
+ delete self->message_factory;
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
}
@@ -384,22 +400,43 @@ PyTypeObject PyDescriptorPool_Type = {
PyObject_Del, // tp_free
};
-static PyDescriptorPool* global_cdescriptor_pool = NULL;
+// This is the DescriptorPool which contains all the definitions from the
+// generated _pb2.py modules.
+static PyDescriptorPool* python_generated_pool = NULL;
bool InitDescriptorPool() {
if (PyType_Ready(&PyDescriptorPool_Type) < 0)
return false;
- global_cdescriptor_pool = cdescriptor_pool::NewDescriptorPool();
- if (global_cdescriptor_pool == NULL) {
+ python_generated_pool = cdescriptor_pool::NewDescriptorPool();
+ if (python_generated_pool == NULL) {
return false;
}
+ // Register this pool to be found for C++-generated descriptors.
+ descriptor_pool_map.insert(
+ std::make_pair(DescriptorPool::generated_pool(),
+ python_generated_pool));
return true;
}
PyDescriptorPool* GetDescriptorPool() {
- return global_cdescriptor_pool;
+ return python_generated_pool;
+}
+
+PyDescriptorPool* GetDescriptorPool_FromPool(const DescriptorPool* pool) {
+ // Fast path for standard descriptors.
+ if (pool == python_generated_pool->pool ||
+ pool == DescriptorPool::generated_pool()) {
+ return python_generated_pool;
+ }
+ hash_map<const DescriptorPool*, PyDescriptorPool*>::iterator it =
+ descriptor_pool_map.find(pool);
+ if (it != descriptor_pool_map.end()) {
+ PyErr_SetString(PyExc_KeyError, "Unknown descriptor pool");
+ return NULL;
+ }
+ return it->second;
}
} // namespace python
diff --git a/python/google/protobuf/pyext/descriptor_pool.h b/python/google/protobuf/pyext/descriptor_pool.h
index efb1abeb..541d920b 100644
--- a/python/google/protobuf/pyext/descriptor_pool.h
+++ b/python/google/protobuf/pyext/descriptor_pool.h
@@ -38,6 +38,8 @@
namespace google {
namespace protobuf {
+class MessageFactory;
+
namespace python {
// Wraps operations to the global DescriptorPool which contains information
@@ -55,6 +57,14 @@ typedef struct PyDescriptorPool {
DescriptorPool* pool;
+ // DynamicMessageFactory used to create C++ instances of messages.
+ // This object cache the descriptors that were used, so the DescriptorPool
+ // needs to get rid of it before it can delete itself.
+ //
+ // Note: A C++ MessageFactory is different from the Python MessageFactory.
+ // The C++ one creates messages, when the Python one creates classes.
+ MessageFactory* message_factory;
+
// Make our own mapping to retrieve Python classes from C++ descriptors.
//
// Descriptor pointers stored here are owned by the DescriptorPool above.
@@ -62,14 +72,6 @@ typedef struct PyDescriptorPool {
typedef hash_map<const Descriptor*, PyObject*> ClassesByMessageMap;
ClassesByMessageMap* classes_by_descriptor;
- // Store interned descriptors, so that the same C++ descriptor yields the same
- // Python object. Objects are not immortal: this map does not own the
- // references, and items are deleted when the last reference to the object is
- // released.
- // This is enough to support the "is" operator on live objects.
- // All descriptors are stored here.
- hash_map<const void*, PyObject*>* interned_descriptors;
-
// Cache the options for any kind of descriptor.
// Descriptor pointers are owned by the DescriptorPool above.
// Python objects are owned by the map.
@@ -81,9 +83,6 @@ extern PyTypeObject PyDescriptorPool_Type;
namespace cdescriptor_pool {
-// Builds a new DescriptorPool. Normally called only once per process.
-PyDescriptorPool* NewDescriptorPool();
-
// Looks up a message by name.
// Returns a message Descriptor, or NULL if not found.
const Descriptor* FindMessageTypeByName(PyDescriptorPool* self,
@@ -140,6 +139,10 @@ PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg);
// Returns a *borrowed* reference.
PyDescriptorPool* GetDescriptorPool();
+// Retrieve the python descriptor pool owning a C++ descriptor pool.
+// Returns a *borrowed* reference.
+PyDescriptorPool* GetDescriptorPool_FromPool(const DescriptorPool* pool);
+
// Initialize objects used by this module.
bool InitDescriptorPool();
diff --git a/python/google/protobuf/pyext/extension_dict.cc b/python/google/protobuf/pyext/extension_dict.cc
index b8d18f8d..8ebbb27c 100644
--- a/python/google/protobuf/pyext/extension_dict.cc
+++ b/python/google/protobuf/pyext/extension_dict.cc
@@ -33,6 +33,7 @@
#include <google/protobuf/pyext/extension_dict.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/dynamic_message.h>
@@ -183,7 +184,8 @@ PyObject* ClearExtension(ExtensionDict* self, PyObject* extension) {
return NULL;
}
}
- if (cmessage::ClearFieldByDescriptor(self->parent, descriptor) == NULL) {
+ if (ScopedPyObjectPtr(cmessage::ClearFieldByDescriptor(
+ self->parent, descriptor)) == NULL) {
return NULL;
}
if (PyDict_DelItem(self->values, extension) < 0) {
@@ -268,7 +270,7 @@ PyTypeObject ExtensionDict_Type = {
0, // tp_as_number
0, // tp_as_sequence
&extension_dict::MpMethods, // tp_as_mapping
- 0, // tp_hash
+ PyObject_HashNotImplemented, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc
index a4843e8d..04544cad 100644
--- a/python/google/protobuf/pyext/message.cc
+++ b/python/google/protobuf/pyext/message.cc
@@ -49,9 +49,10 @@
#endif
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/util/message_differencer.h>
#include <google/protobuf/descriptor.h>
-#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/message.h>
#include <google/protobuf/text_format.h>
#include <google/protobuf/pyext/descriptor.h>
@@ -88,12 +89,308 @@ namespace google {
namespace protobuf {
namespace python {
+static PyObject* kDESCRIPTOR;
+static PyObject* k_extensions_by_name;
+static PyObject* k_extensions_by_number;
+PyObject* EnumTypeWrapper_class;
+static PyObject* PythonMessage_class;
+static PyObject* kEmptyWeakref;
+
+// 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;
+};
+
+namespace message_meta {
+
+static int InsertEmptyWeakref(PyTypeObject* base);
+
+// Add the number of a field descriptor to the containing message class.
+// Equivalent to:
+// _cls.<field>_FIELD_NUMBER = <number>
+static bool AddFieldNumberToClass(
+ PyObject* cls, const FieldDescriptor* field_descriptor) {
+ string constant_name = field_descriptor->name() + "_FIELD_NUMBER";
+ UpperString(&constant_name);
+ ScopedPyObjectPtr attr_name(PyString_FromStringAndSize(
+ constant_name.c_str(), constant_name.size()));
+ if (attr_name == NULL) {
+ return false;
+ }
+ ScopedPyObjectPtr number(PyInt_FromLong(field_descriptor->number()));
+ if (number == NULL) {
+ return false;
+ }
+ if (PyObject_SetAttr(cls, attr_name, number) == -1) {
+ return false;
+ }
+ return true;
+}
+
+
+// Finalize the creation of the Message class.
+// Called from its metaclass: GeneratedProtocolMessageType.__init__().
+static int AddDescriptors(PyObject* cls, PyObject* descriptor) {
+ const Descriptor* message_descriptor =
+ cdescriptor_pool::RegisterMessageClass(
+ GetDescriptorPool(), cls, descriptor);
+ if (message_descriptor == NULL) {
+ return -1;
+ }
+
+ // If there are extension_ranges, the message is "extendable", and extension
+ // classes will register themselves in this class.
+ if (message_descriptor->extension_range_count() > 0) {
+ ScopedPyObjectPtr by_name(PyDict_New());
+ if (PyObject_SetAttr(cls, k_extensions_by_name, by_name) < 0) {
+ return -1;
+ }
+ ScopedPyObjectPtr by_number(PyDict_New());
+ if (PyObject_SetAttr(cls, k_extensions_by_number, by_number) < 0) {
+ return -1;
+ }
+ }
+
+ // For each field set: cls.<field>_FIELD_NUMBER = <number>
+ for (int i = 0; i < message_descriptor->field_count(); ++i) {
+ if (!AddFieldNumberToClass(cls, message_descriptor->field(i))) {
+ return -1;
+ }
+ }
+
+ // 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 < message_descriptor->enum_type_count(); ++i) {
+ const EnumDescriptor* enum_descriptor = message_descriptor->enum_type(i);
+ ScopedPyObjectPtr enum_type(
+ PyEnumDescriptor_FromDescriptor(enum_descriptor));
+ if (enum_type == NULL) {
+ return -1;
+ }
+ // Add wrapped enum type to message class.
+ ScopedPyObjectPtr wrapped(PyObject_CallFunctionObjArgs(
+ EnumTypeWrapper_class, enum_type.get(), NULL));
+ if (wrapped == NULL) {
+ return -1;
+ }
+ if (PyObject_SetAttrString(
+ cls, enum_descriptor->name().c_str(), wrapped) == -1) {
+ return -1;
+ }
+
+ // For each enum value add cls.<name> = <number>
+ for (int j = 0; j < enum_descriptor->value_count(); ++j) {
+ const EnumValueDescriptor* enum_value_descriptor =
+ enum_descriptor->value(j);
+ ScopedPyObjectPtr value_number(PyInt_FromLong(
+ enum_value_descriptor->number()));
+ if (value_number == NULL) {
+ return -1;
+ }
+ if (PyObject_SetAttrString(
+ cls, enum_value_descriptor->name().c_str(), value_number) == -1) {
+ return -1;
+ }
+ }
+ }
+
+ // For each extension set cls.<extension name> = <extension descriptor>.
+ //
+ // Extension descriptors come from
+ // <message descriptor>.extensions_by_name[name]
+ // which was defined previously.
+ for (int i = 0; i < message_descriptor->extension_count(); ++i) {
+ const google::protobuf::FieldDescriptor* field = message_descriptor->extension(i);
+ ScopedPyObjectPtr extension_field(PyFieldDescriptor_FromDescriptor(field));
+ if (extension_field == NULL) {
+ return -1;
+ }
+
+ // Add the extension field to the message class.
+ if (PyObject_SetAttrString(
+ cls, field->name().c_str(), extension_field) == -1) {
+ return -1;
+ }
+
+ // For each extension set cls.<extension name>_FIELD_NUMBER = <number>.
+ if (!AddFieldNumberToClass(cls, field)) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static PyObject* New(PyTypeObject* type,
+ PyObject* args, PyObject* kwargs) {
+ static char *kwlist[] = {"name", "bases", "dict", 0};
+ PyObject *bases, *dict;
+ const char* name;
+
+ // Check arguments: (name, bases, dict)
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO!O!:type", kwlist,
+ &name,
+ &PyTuple_Type, &bases,
+ &PyDict_Type, &dict)) {
+ return NULL;
+ }
+
+ // Check bases: only (), or (message.Message,) are allowed
+ if (!(PyTuple_GET_SIZE(bases) == 0 ||
+ (PyTuple_GET_SIZE(bases) == 1 &&
+ PyTuple_GET_ITEM(bases, 0) == PythonMessage_class))) {
+ PyErr_SetString(PyExc_TypeError,
+ "A Message class can only inherit from Message");
+ return NULL;
+ }
+
+ // Check dict['DESCRIPTOR']
+ PyObject* descriptor = PyDict_GetItem(dict, kDESCRIPTOR);
+ if (descriptor == NULL) {
+ PyErr_SetString(PyExc_TypeError, "Message class has no DESCRIPTOR");
+ return NULL;
+ }
+ if (!PyObject_TypeCheck(descriptor, &PyMessageDescriptor_Type)) {
+ PyErr_Format(PyExc_TypeError, "Expected a message Descriptor, got %s",
+ descriptor->ob_type->tp_name);
+ return NULL;
+ }
+
+ // Build the arguments to the base metaclass.
+ // We change the __bases__ classes.
+ ScopedPyObjectPtr new_args(Py_BuildValue(
+ "s(OO)O", name, &CMessage_Type, PythonMessage_class, dict));
+ if (new_args == NULL) {
+ return NULL;
+ }
+ // Call the base metaclass.
+ ScopedPyObjectPtr result(PyType_Type.tp_new(type, new_args, NULL));
+ if (result == NULL) {
+ return NULL;
+ }
+ PyMessageMeta* newtype = reinterpret_cast<PyMessageMeta*>(result.get());
+
+ // Insert the empty weakref into the base classes.
+ if (InsertEmptyWeakref(
+ reinterpret_cast<PyTypeObject*>(PythonMessage_class)) < 0 ||
+ InsertEmptyWeakref(&CMessage_Type) < 0) {
+ return NULL;
+ }
+
+ // Cache the descriptor, both as Python object and as C++ pointer.
+ const Descriptor* message_descriptor =
+ PyMessageDescriptor_AsDescriptor(descriptor);
+ if (message_descriptor == NULL) {
+ return NULL;
+ }
+ Py_INCREF(descriptor);
+ newtype->py_message_descriptor = descriptor;
+ newtype->message_descriptor = message_descriptor;
+
+ // Continue with type initialization: add other descriptors, enum values...
+ if (AddDescriptors(result, descriptor) < 0) {
+ return NULL;
+ }
+ return result.release();
+}
+
+static void Dealloc(PyMessageMeta *self) {
+ Py_DECREF(self->py_message_descriptor);
+ Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+static PyObject* GetDescriptor(PyMessageMeta *self, void *closure) {
+ Py_INCREF(self->py_message_descriptor);
+ return self->py_message_descriptor;
+}
+
+
+// This function inserts and empty weakref at the end of the list of
+// subclasses for the main protocol buffer Message class.
+//
+// This eliminates a O(n^2) behaviour in the internal add_subclass
+// routine.
+static int InsertEmptyWeakref(PyTypeObject *base_type) {
+#if PY_MAJOR_VERSION >= 3
+ // Python 3.4 has already included the fix for the issue that this
+ // hack addresses. For further background and the fix please see
+ // https://bugs.python.org/issue17936.
+ return 0;
+#else
+ PyObject *subclasses = base_type->tp_subclasses;
+ if (subclasses && PyList_CheckExact(subclasses)) {
+ return PyList_Append(subclasses, kEmptyWeakref);
+ }
+ return 0;
+#endif // PY_MAJOR_VERSION >= 3
+}
+
+} // namespace message_meta
+
+PyTypeObject PyMessageMeta_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ FULL_MODULE_NAME ".MessageMeta", // tp_name
+ sizeof(PyMessageMeta), // tp_basicsize
+ 0, // tp_itemsize
+ (destructor)message_meta::Dealloc, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags
+ "The metaclass of ProtocolMessages", // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ message_meta::New, // tp_new
+};
+
+static const Descriptor* GetMessageDescriptor(PyTypeObject* cls) {
+ if (!PyObject_TypeCheck(cls, &PyMessageMeta_Type)) {
+ PyErr_Format(PyExc_TypeError, "Class %s is not a Message", cls->tp_name);
+ return NULL;
+ }
+ return reinterpret_cast<PyMessageMeta*>(cls)->message_descriptor;
+}
+
// Forward declarations
namespace cmessage {
-static const FieldDescriptor* GetFieldDescriptor(
- CMessage* self, PyObject* name);
-static const Descriptor* GetMessageDescriptor(PyTypeObject* cls);
-static string GetMessageName(CMessage* self);
int InternalReleaseFieldByDescriptor(
CMessage* self,
const FieldDescriptor* field_descriptor,
@@ -180,7 +477,7 @@ int ForEachCompositeField(CMessage* self, Visitor visitor) {
if (self->composite_fields) {
// Never use self->message in this function, it may be already freed.
const Descriptor* message_descriptor =
- cmessage::GetMessageDescriptor(Py_TYPE(self));
+ GetMessageDescriptor(Py_TYPE(self));
while (PyDict_Next(self->composite_fields, &pos, &key, &field)) {
Py_ssize_t key_str_size;
char *key_str_data;
@@ -213,8 +510,6 @@ int ForEachCompositeField(CMessage* self, Visitor visitor) {
// ---------------------------------------------------------------------
-static DynamicMessageFactory* message_factory;
-
// Constants used for integer type range checking.
PyObject* kPythonZero;
PyObject* kint32min_py;
@@ -224,17 +519,13 @@ PyObject* kint64min_py;
PyObject* kint64max_py;
PyObject* kuint64max_py;
-PyObject* EnumTypeWrapper_class;
PyObject* EncodeError_class;
PyObject* DecodeError_class;
PyObject* PickleError_class;
// Constant PyString values used for GetAttr/GetItem.
-static PyObject* kDESCRIPTOR;
static PyObject* k_cdescriptor;
static PyObject* kfull_name;
-static PyObject* k_extensions_by_name;
-static PyObject* k_extensions_by_number;
/* Is 64bit */
void FormatTypeError(PyObject* arg, char* expected_types) {
@@ -432,10 +723,6 @@ bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor,
namespace cmessage {
-DynamicMessageFactory* GetMessageFactory() {
- return message_factory;
-}
-
static int MaybeReleaseOverlappingOneofField(
CMessage* cmessage,
const FieldDescriptor* field) {
@@ -486,7 +773,7 @@ static Message* GetMutableMessage(
return NULL;
}
return reflection->MutableMessage(
- parent_message, parent_field, message_factory);
+ parent_message, parent_field, GetDescriptorPool()->message_factory);
}
struct FixupMessageReference : public ChildVisitor {
@@ -527,8 +814,9 @@ int AssureWritable(CMessage* self) {
// If parent is NULL but we are trying to modify a read-only message, this
// is a reference to a constant default instance that needs to be replaced
// with a mutable top-level message.
- const Message* prototype = message_factory->GetPrototype(
- self->message->GetDescriptor());
+ const Message* prototype =
+ GetDescriptorPool()->message_factory->GetPrototype(
+ self->message->GetDescriptor());
self->message = prototype->New();
self->owner.reset(self->message);
// Cascade the new owner to eventual children: even if this message is
@@ -567,23 +855,6 @@ int AssureWritable(CMessage* self) {
// --- Globals:
-// Retrieve the C++ Descriptor of a message class.
-// On error, returns NULL with an exception set.
-static const Descriptor* GetMessageDescriptor(PyTypeObject* cls) {
- ScopedPyObjectPtr descriptor(PyObject_GetAttr(
- reinterpret_cast<PyObject*>(cls), kDESCRIPTOR));
- if (descriptor == NULL) {
- PyErr_SetString(PyExc_TypeError, "Message class has no DESCRIPTOR");
- return NULL;
- }
- if (!PyObject_TypeCheck(descriptor, &PyMessageDescriptor_Type)) {
- PyErr_Format(PyExc_TypeError, "Expected a message Descriptor, got %s",
- descriptor->ob_type->tp_name);
- return NULL;
- }
- return PyMessageDescriptor_AsDescriptor(descriptor);
-}
-
// Retrieve a C++ FieldDescriptor for a message attribute.
// The C++ message must be valid.
// TODO(amauryfa): This function should stay internal, because exception
@@ -846,9 +1117,9 @@ int InitAttributes(CMessage* self, PyObject* kwargs) {
return -1;
}
} else {
- if (repeated_scalar_container::Extend(
+ if (ScopedPyObjectPtr(repeated_scalar_container::Extend(
reinterpret_cast<RepeatedScalarContainer*>(container.get()),
- value) ==
+ value)) ==
NULL) {
return -1;
}
@@ -927,7 +1198,7 @@ static PyObject* New(PyTypeObject* type,
return NULL;
}
const Message* default_message =
- message_factory->GetPrototype(message_descriptor);
+ GetDescriptorPool()->message_factory->GetPrototype(message_descriptor);
if (default_message == NULL) {
PyErr_SetString(PyExc_TypeError, message_descriptor->full_name().c_str());
return NULL;
@@ -1257,6 +1528,7 @@ int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner) {
Message* ReleaseMessage(CMessage* self,
const Descriptor* descriptor,
const FieldDescriptor* field_descriptor) {
+ MessageFactory* message_factory = GetDescriptorPool()->message_factory;
Message* released_message = self->message->GetReflection()->ReleaseMessage(
self->message, field_descriptor, message_factory);
// ReleaseMessage will return NULL which differs from
@@ -1492,34 +1764,38 @@ static PyObject* SerializePartialToString(CMessage* self) {
// appropriate.
class PythonFieldValuePrinter : public TextFormat::FieldValuePrinter {
public:
- PythonFieldValuePrinter() : float_holder_(PyFloat_FromDouble(0)) {}
-
// Python has some differences from C++ when printing floating point numbers.
//
// 1) Trailing .0 is always printed.
- // 2) Outputted is rounded to 12 digits.
+ // 2) (Python2) Output is rounded to 12 digits.
+ // 3) (Python3) The full precision of the double is preserved (and Python uses
+ // David M. Gay's dtoa(), when the C++ code uses SimpleDtoa. There are some
+ // differences, but they rarely happen)
//
// We override floating point printing with the C-API function for printing
// Python floats to ensure consistency.
string PrintFloat(float value) const { return PrintDouble(value); }
string PrintDouble(double value) const {
- reinterpret_cast<PyFloatObject*>(float_holder_.get())->ob_fval = value;
- ScopedPyObjectPtr s(PyObject_Str(float_holder_.get()));
- if (s == NULL) return string();
-#if PY_MAJOR_VERSION < 3
- char *cstr = PyBytes_AS_STRING(static_cast<PyObject*>(s));
-#else
- char *cstr = PyUnicode_AsUTF8(s);
-#endif
- return string(cstr);
- }
+ // This implementation is not highly optimized (it allocates two temporary
+ // Python objects) but it is simple and portable. If this is shown to be a
+ // performance bottleneck, we can optimize it, but the results will likely
+ // be more complicated to accommodate the differing behavior of double
+ // formatting between Python 2 and Python 3.
+ //
+ // (Though a valid question is: do we really want to make out output
+ // dependent on the Python version?)
+ ScopedPyObjectPtr py_value(PyFloat_FromDouble(value));
+ if (!py_value.get()) {
+ return string();
+ }
- private:
- // Holder for a python float object which we use to allow us to use
- // the Python API for printing doubles. We initialize once and then
- // directly modify it for every float printed to save on allocations
- // and refcounting.
- ScopedPyObjectPtr float_holder_;
+ ScopedPyObjectPtr py_str(PyObject_Str(py_value.get()));
+ if (!py_str.get()) {
+ return string();
+ }
+
+ return string(PyString_AsString(py_str.get()));
+ }
};
static PyObject* ToStr(CMessage* self) {
@@ -1590,7 +1866,7 @@ static PyObject* CopyFrom(CMessage* self, PyObject* arg) {
// CopyFrom on the message will not clean up self->composite_fields,
// which can leave us in an inconsistent state, so clear it out here.
- Clear(self);
+ (void)ScopedPyObjectPtr(Clear(self));
self->message->CopyFrom(*other_message->message);
@@ -1607,7 +1883,8 @@ static PyObject* MergeFromString(CMessage* self, PyObject* arg) {
AssureWritable(self);
io::CodedInputStream input(
reinterpret_cast<const uint8*>(data), data_length);
- input.SetExtensionRegistry(GetDescriptorPool()->pool, message_factory);
+ input.SetExtensionRegistry(GetDescriptorPool()->pool,
+ GetDescriptorPool()->message_factory);
bool success = self->message->MergePartialFromCodedStream(&input);
if (success) {
return PyInt_FromLong(input.CurrentPosition());
@@ -1618,7 +1895,7 @@ static PyObject* MergeFromString(CMessage* self, PyObject* arg) {
}
static PyObject* ParseFromString(CMessage* self, PyObject* arg) {
- if (Clear(self) == NULL) {
+ if (ScopedPyObjectPtr(Clear(self)) == NULL) {
return NULL;
}
return MergeFromString(self, arg);
@@ -1790,6 +2067,7 @@ static PyObject* ListFields(CMessage* self) {
// Steals reference to 'extension'
PyTuple_SET_ITEM(t.get(), 1, extension);
} else {
+ // Normal field
const string& field_name = fields[i]->name();
ScopedPyObjectPtr py_field_name(PyString_FromStringAndSize(
field_name.c_str(), field_name.length()));
@@ -1841,28 +2119,34 @@ PyObject* FindInitializationErrors(CMessage* self) {
}
static PyObject* RichCompare(CMessage* self, PyObject* other, int opid) {
- if (!PyObject_TypeCheck(other, &CMessage_Type)) {
- if (opid == Py_EQ) {
- Py_RETURN_FALSE;
- } else if (opid == Py_NE) {
- Py_RETURN_TRUE;
- }
- }
- if (opid == Py_EQ || opid == Py_NE) {
- ScopedPyObjectPtr self_fields(ListFields(self));
- if (!self_fields) {
- return NULL;
- }
- ScopedPyObjectPtr other_fields(ListFields(
- reinterpret_cast<CMessage*>(other)));
- if (!other_fields) {
- return NULL;
- }
- return PyObject_RichCompare(self_fields, other_fields, opid);
- } else {
+ // Only equality comparisons are implemented.
+ if (opid != Py_EQ && opid != Py_NE) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
+ bool equals = true;
+ // If other is not a message, it cannot be equal.
+ if (!PyObject_TypeCheck(other, &CMessage_Type)) {
+ equals = false;
+ }
+ const google::protobuf::Message* other_message =
+ reinterpret_cast<CMessage*>(other)->message;
+ // If messages don't have the same descriptors, they are not equal.
+ if (equals &&
+ self->message->GetDescriptor() != other_message->GetDescriptor()) {
+ equals = false;
+ }
+ // Check the message contents.
+ if (equals && !google::protobuf::util::MessageDifferencer::Equals(
+ *self->message,
+ *reinterpret_cast<CMessage*>(other)->message)) {
+ equals = false;
+ }
+ if (equals ^ (opid == Py_EQ)) {
+ Py_RETURN_FALSE;
+ } else {
+ Py_RETURN_TRUE;
+ }
}
PyObject* InternalGetScalar(const Message* message,
@@ -1950,7 +2234,7 @@ PyObject* InternalGetSubMessage(
CMessage* self, const FieldDescriptor* field_descriptor) {
const Reflection* reflection = self->message->GetReflection();
const Message& sub_message = reflection->GetMessage(
- *self->message, field_descriptor, message_factory);
+ *self->message, field_descriptor, GetDescriptorPool()->message_factory);
PyObject *message_class = cdescriptor_pool::GetMessageClass(
GetDescriptorPool(), field_descriptor->message_type());
@@ -2085,125 +2369,6 @@ PyObject* FromString(PyTypeObject* cls, PyObject* serialized) {
return py_cmsg;
}
-// Add the number of a field descriptor to the containing message class.
-// Equivalent to:
-// _cls.<field>_FIELD_NUMBER = <number>
-static bool AddFieldNumberToClass(
- PyObject* cls, const FieldDescriptor* field_descriptor) {
- string constant_name = field_descriptor->name() + "_FIELD_NUMBER";
- UpperString(&constant_name);
- ScopedPyObjectPtr attr_name(PyString_FromStringAndSize(
- constant_name.c_str(), constant_name.size()));
- if (attr_name == NULL) {
- return false;
- }
- ScopedPyObjectPtr number(PyInt_FromLong(field_descriptor->number()));
- if (number == NULL) {
- return false;
- }
- if (PyObject_SetAttr(cls, attr_name, number) == -1) {
- return false;
- }
- return true;
-}
-
-
-// Finalize the creation of the Message class.
-// Called from its metaclass: GeneratedProtocolMessageType.__init__().
-static PyObject* AddDescriptors(PyObject* cls, PyObject* descriptor) {
- const Descriptor* message_descriptor =
- cdescriptor_pool::RegisterMessageClass(
- GetDescriptorPool(), cls, descriptor);
- if (message_descriptor == NULL) {
- return NULL;
- }
-
- // If there are extension_ranges, the message is "extendable", and extension
- // classes will register themselves in this class.
- if (message_descriptor->extension_range_count() > 0) {
- ScopedPyObjectPtr by_name(PyDict_New());
- if (PyObject_SetAttr(cls, k_extensions_by_name, by_name) < 0) {
- return NULL;
- }
- ScopedPyObjectPtr by_number(PyDict_New());
- if (PyObject_SetAttr(cls, k_extensions_by_number, by_number) < 0) {
- return NULL;
- }
- }
-
- // For each field set: cls.<field>_FIELD_NUMBER = <number>
- for (int i = 0; i < message_descriptor->field_count(); ++i) {
- if (!AddFieldNumberToClass(cls, message_descriptor->field(i))) {
- return NULL;
- }
- }
-
- // 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 < message_descriptor->enum_type_count(); ++i) {
- const EnumDescriptor* enum_descriptor = message_descriptor->enum_type(i);
- ScopedPyObjectPtr enum_type(
- PyEnumDescriptor_FromDescriptor(enum_descriptor));
- if (enum_type == NULL) {
- return NULL;
- }
- // Add wrapped enum type to message class.
- ScopedPyObjectPtr wrapped(PyObject_CallFunctionObjArgs(
- EnumTypeWrapper_class, enum_type.get(), NULL));
- if (wrapped == NULL) {
- return NULL;
- }
- if (PyObject_SetAttrString(
- cls, enum_descriptor->name().c_str(), wrapped) == -1) {
- return NULL;
- }
-
- // For each enum value add cls.<name> = <number>
- for (int j = 0; j < enum_descriptor->value_count(); ++j) {
- const EnumValueDescriptor* enum_value_descriptor =
- enum_descriptor->value(j);
- ScopedPyObjectPtr value_number(PyInt_FromLong(
- enum_value_descriptor->number()));
- if (value_number == NULL) {
- return NULL;
- }
- if (PyObject_SetAttrString(
- cls, enum_value_descriptor->name().c_str(), value_number) == -1) {
- return NULL;
- }
- }
- }
-
- // For each extension set cls.<extension name> = <extension descriptor>.
- //
- // Extension descriptors come from
- // <message descriptor>.extensions_by_name[name]
- // which was defined previously.
- for (int i = 0; i < message_descriptor->extension_count(); ++i) {
- const google::protobuf::FieldDescriptor* field = message_descriptor->extension(i);
- ScopedPyObjectPtr extension_field(PyFieldDescriptor_FromDescriptor(field));
- if (extension_field == NULL) {
- return NULL;
- }
-
- // Add the extension field to the message class.
- if (PyObject_SetAttrString(
- cls, field->name().c_str(), extension_field) == -1) {
- return NULL;
- }
-
- // For each extension set cls.<extension name>_FIELD_NUMBER = <number>.
- if (!AddFieldNumberToClass(cls, field)) {
- return NULL;
- }
- }
-
- Py_RETURN_NONE;
-}
-
PyObject* DeepCopy(CMessage* self, PyObject* arg) {
PyObject* clone = PyObject_CallObject(
reinterpret_cast<PyObject*>(Py_TYPE(self)), NULL);
@@ -2214,8 +2379,9 @@ PyObject* DeepCopy(CMessage* self, PyObject* arg) {
Py_DECREF(clone);
return NULL;
}
- if (MergeFrom(reinterpret_cast<CMessage*>(clone),
- reinterpret_cast<PyObject*>(self)) == NULL) {
+ if (ScopedPyObjectPtr(MergeFrom(
+ reinterpret_cast<CMessage*>(clone),
+ reinterpret_cast<PyObject*>(self))) == NULL) {
Py_DECREF(clone);
return NULL;
}
@@ -2281,7 +2447,7 @@ PyObject* SetState(CMessage* self, PyObject* state) {
if (serialized == NULL) {
return NULL;
}
- if (ParseFromString(self, serialized) == NULL) {
+ if (ScopedPyObjectPtr(ParseFromString(self, serialized)) == NULL) {
return NULL;
}
Py_RETURN_NONE;
@@ -2314,8 +2480,6 @@ static PyMethodDef Methods[] = {
"Inputs picklable representation of the message." },
{ "__unicode__", (PyCFunction)ToUnicode, METH_NOARGS,
"Outputs a unicode representation of the message." },
- { "AddDescriptors", (PyCFunction)AddDescriptors, METH_O | METH_CLASS,
- "Adds field descriptors to the class" },
{ "ByteSize", (PyCFunction)ByteSize, METH_NOARGS,
"Returns the size of the message in bytes." },
{ "Clear", (PyCFunction)Clear, METH_NOARGS,
@@ -2441,6 +2605,9 @@ PyObject* GetAttr(CMessage* self, PyObject* name) {
if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
PyObject* sub_message = InternalGetSubMessage(self, field_descriptor);
+ if (sub_message == NULL) {
+ return NULL;
+ }
if (!SetCompositeField(self, name, sub_message)) {
Py_DECREF(sub_message);
return NULL;
@@ -2484,7 +2651,7 @@ int SetAttr(CMessage* self, PyObject* name, PyObject* value) {
} // namespace cmessage
PyTypeObject CMessage_Type = {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ PyVarObject_HEAD_INIT(&PyMessageMeta_Type, 0)
FULL_MODULE_NAME ".CMessage", // tp_name
sizeof(CMessage), // tp_basicsize
0, // tp_itemsize
@@ -2497,7 +2664,7 @@ PyTypeObject CMessage_Type = {
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
- 0, // tp_hash
+ PyObject_HashNotImplemented, // tp_hash
0, // tp_call
(reprfunc)cmessage::ToStr, // tp_str
(getattrofunc)cmessage::GetAttr, // tp_getattro
@@ -2580,8 +2747,9 @@ void InitGlobals() {
k_extensions_by_name = PyString_FromString("_extensions_by_name");
k_extensions_by_number = PyString_FromString("_extensions_by_number");
- message_factory = new DynamicMessageFactory();
- message_factory->SetDelegateToGeneratedFactory(true);
+ PyObject *dummy_obj = PySet_New(NULL);
+ kEmptyWeakref = PyWeakref_NewRef(dummy_obj, NULL);
+ Py_DECREF(dummy_obj);
}
bool InitProto2MessageModule(PyObject *m) {
@@ -2598,7 +2766,13 @@ bool InitProto2MessageModule(PyObject *m) {
// Initialize constants defined in this file.
InitGlobals();
- CMessage_Type.tp_hash = PyObject_HashNotImplemented;
+ PyMessageMeta_Type.tp_base = &PyType_Type;
+ if (PyType_Ready(&PyMessageMeta_Type) < 0) {
+ return false;
+ }
+ PyModule_AddObject(m, "MessageMeta",
+ reinterpret_cast<PyObject*>(&PyMessageMeta_Type));
+
if (PyType_Ready(&CMessage_Type) < 0) {
return false;
}
@@ -2628,86 +2802,122 @@ bool InitProto2MessageModule(PyObject *m) {
PyModule_AddObject(m, "Message", reinterpret_cast<PyObject*>(&CMessage_Type));
- RepeatedScalarContainer_Type.tp_hash =
- PyObject_HashNotImplemented;
- if (PyType_Ready(&RepeatedScalarContainer_Type) < 0) {
- return false;
- }
+ // Initialize Repeated container types.
+ {
+ if (PyType_Ready(&RepeatedScalarContainer_Type) < 0) {
+ return false;
+ }
- PyModule_AddObject(m, "RepeatedScalarContainer",
- reinterpret_cast<PyObject*>(
- &RepeatedScalarContainer_Type));
+ PyModule_AddObject(m, "RepeatedScalarContainer",
+ reinterpret_cast<PyObject*>(
+ &RepeatedScalarContainer_Type));
- RepeatedCompositeContainer_Type.tp_hash = PyObject_HashNotImplemented;
- if (PyType_Ready(&RepeatedCompositeContainer_Type) < 0) {
- return false;
- }
+ if (PyType_Ready(&RepeatedCompositeContainer_Type) < 0) {
+ return false;
+ }
- PyModule_AddObject(
- m, "RepeatedCompositeContainer",
- reinterpret_cast<PyObject*>(
- &RepeatedCompositeContainer_Type));
-
- // ScalarMapContainer_Type derives from our MutableMapping type.
- PyObject* containers =
- PyImport_ImportModule("google.protobuf.internal.containers");
- if (containers == NULL) {
- return false;
+ PyModule_AddObject(
+ m, "RepeatedCompositeContainer",
+ reinterpret_cast<PyObject*>(
+ &RepeatedCompositeContainer_Type));
+
+ // Register them as collections.Sequence
+ ScopedPyObjectPtr collections(PyImport_ImportModule("collections"));
+ if (collections == NULL) {
+ return false;
+ }
+ ScopedPyObjectPtr mutable_sequence(PyObject_GetAttrString(
+ collections, "MutableSequence"));
+ if (mutable_sequence == NULL) {
+ return false;
+ }
+ if (ScopedPyObjectPtr(PyObject_CallMethod(mutable_sequence, "register", "O",
+ &RepeatedScalarContainer_Type))
+ == NULL) {
+ return false;
+ }
+ if (ScopedPyObjectPtr(PyObject_CallMethod(mutable_sequence, "register", "O",
+ &RepeatedCompositeContainer_Type))
+ == NULL) {
+ return false;
+ }
}
- PyObject* mutable_mapping =
- PyObject_GetAttrString(containers, "MutableMapping");
- Py_DECREF(containers);
+ // Initialize Map container types.
+ {
+ // ScalarMapContainer_Type derives from our MutableMapping type.
+ ScopedPyObjectPtr containers(PyImport_ImportModule(
+ "google.protobuf.internal.containers"));
+ if (containers == NULL) {
+ return false;
+ }
- if (mutable_mapping == NULL) {
- return false;
- }
+ ScopedPyObjectPtr mutable_mapping(
+ PyObject_GetAttrString(containers, "MutableMapping"));
+ if (mutable_mapping == NULL) {
+ return false;
+ }
- if (!PyObject_TypeCheck(mutable_mapping, &PyType_Type)) {
- Py_DECREF(mutable_mapping);
- return false;
- }
+ if (!PyObject_TypeCheck(mutable_mapping, &PyType_Type)) {
+ return false;
+ }
- ScalarMapContainer_Type.tp_base =
- reinterpret_cast<PyTypeObject*>(mutable_mapping);
+ Py_INCREF(mutable_mapping);
+#if PY_MAJOR_VERSION >= 3
+ PyObject* bases = PyTuple_New(1);
+ PyTuple_SET_ITEM(bases, 0, mutable_mapping.get());
- if (PyType_Ready(&ScalarMapContainer_Type) < 0) {
- return false;
- }
+ ScalarMapContainer_Type =
+ PyType_FromSpecWithBases(&ScalarMapContainer_Type_spec, bases);
+ PyModule_AddObject(m, "ScalarMapContainer", ScalarMapContainer_Type);
+#else
+ ScalarMapContainer_Type.tp_base =
+ reinterpret_cast<PyTypeObject*>(mutable_mapping.get());
- PyModule_AddObject(m, "ScalarMapContainer",
- reinterpret_cast<PyObject*>(&ScalarMapContainer_Type));
+ if (PyType_Ready(&ScalarMapContainer_Type) < 0) {
+ return false;
+ }
- if (PyType_Ready(&ScalarMapIterator_Type) < 0) {
- return false;
- }
+ PyModule_AddObject(m, "ScalarMapContainer",
+ reinterpret_cast<PyObject*>(&ScalarMapContainer_Type));
+#endif
- PyModule_AddObject(m, "ScalarMapIterator",
- reinterpret_cast<PyObject*>(&ScalarMapIterator_Type));
+ if (PyType_Ready(&ScalarMapIterator_Type) < 0) {
+ return false;
+ }
- Py_INCREF(mutable_mapping);
- MessageMapContainer_Type.tp_base =
- reinterpret_cast<PyTypeObject*>(mutable_mapping);
+ PyModule_AddObject(m, "ScalarMapIterator",
+ reinterpret_cast<PyObject*>(&ScalarMapIterator_Type));
- if (PyType_Ready(&MessageMapContainer_Type) < 0) {
- return false;
- }
- PyModule_AddObject(m, "MessageMapContainer",
- reinterpret_cast<PyObject*>(&MessageMapContainer_Type));
+#if PY_MAJOR_VERSION >= 3
+ MessageMapContainer_Type =
+ PyType_FromSpecWithBases(&MessageMapContainer_Type_spec, bases);
+ PyModule_AddObject(m, "MessageMapContainer", MessageMapContainer_Type);
+#else
+ Py_INCREF(mutable_mapping);
+ MessageMapContainer_Type.tp_base =
+ reinterpret_cast<PyTypeObject*>(mutable_mapping.get());
- if (PyType_Ready(&MessageMapIterator_Type) < 0) {
- return false;
- }
+ if (PyType_Ready(&MessageMapContainer_Type) < 0) {
+ return false;
+ }
+
+ PyModule_AddObject(m, "MessageMapContainer",
+ reinterpret_cast<PyObject*>(&MessageMapContainer_Type));
+#endif
+
+ if (PyType_Ready(&MessageMapIterator_Type) < 0) {
+ return false;
+ }
- PyModule_AddObject(m, "MessageMapIterator",
- reinterpret_cast<PyObject*>(&MessageMapIterator_Type));
+ PyModule_AddObject(m, "MessageMapIterator",
+ reinterpret_cast<PyObject*>(&MessageMapIterator_Type));
+ }
- ExtensionDict_Type.tp_hash = PyObject_HashNotImplemented;
if (PyType_Ready(&ExtensionDict_Type) < 0) {
return false;
}
-
PyModule_AddObject(
m, "ExtensionDict",
reinterpret_cast<PyObject*>(&ExtensionDict_Type));
@@ -2751,6 +2961,7 @@ bool InitProto2MessageModule(PyObject *m) {
}
EncodeError_class = PyObject_GetAttrString(message_module, "EncodeError");
DecodeError_class = PyObject_GetAttrString(message_module, "DecodeError");
+ PythonMessage_class = PyObject_GetAttrString(message_module, "Message");
Py_DECREF(message_module);
PyObject* pickle_module = PyImport_ImportModule("pickle");
diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h
index 7360b207..f147d433 100644
--- a/python/google/protobuf/pyext/message.h
+++ b/python/google/protobuf/pyext/message.h
@@ -49,7 +49,6 @@ class Message;
class Reflection;
class FieldDescriptor;
class Descriptor;
-class DynamicMessageFactory;
using internal::shared_ptr;
@@ -221,9 +220,6 @@ PyObject* FindInitializationErrors(CMessage* self);
int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner);
int AssureWritable(CMessage* self);
-
-DynamicMessageFactory* GetMessageFactory();
-
} // namespace cmessage
diff --git a/python/google/protobuf/pyext/message_map_container.cc b/python/google/protobuf/pyext/message_map_container.cc
index ab8d8fb9..f54d2015 100644
--- a/python/google/protobuf/pyext/message_map_container.cc
+++ b/python/google/protobuf/pyext/message_map_container.cc
@@ -32,6 +32,7 @@
#include <google/protobuf/pyext/message_map_container.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/message.h>
#include <google/protobuf/pyext/message.h>
@@ -83,7 +84,12 @@ PyObject* NewContainer(CMessage* parent,
return NULL;
}
+#if PY_MAJOR_VERSION >= 3
+ PyObject* obj = PyType_GenericAlloc(
+ reinterpret_cast<PyTypeObject *>(MessageMapContainer_Type), 0);
+#else
PyObject* obj = PyType_GenericAlloc(&MessageMapContainer_Type, 0);
+#endif
if (obj == NULL) {
return PyErr_Format(PyExc_RuntimeError,
"Could not allocate new container.");
@@ -457,44 +463,67 @@ PyObject* IterNext(PyObject* _self) {
} // namespace message_map_iterator
-PyTypeObject MessageMapContainer_Type = {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
- FULL_MODULE_NAME ".MessageMapContainer", // tp_name
- sizeof(MessageMapContainer), // tp_basicsize
- 0, // tp_itemsize
- message_map_container::Dealloc, // tp_dealloc
- 0, // tp_print
- 0, // tp_getattr
- 0, // tp_setattr
- 0, // tp_compare
- 0, // tp_repr
- 0, // tp_as_number
- 0, // tp_as_sequence
- &message_map_container::MpMethods, // tp_as_mapping
- 0, // tp_hash
- 0, // tp_call
- 0, // tp_str
- 0, // tp_getattro
- 0, // tp_setattro
- 0, // tp_as_buffer
- Py_TPFLAGS_DEFAULT, // tp_flags
- "A map container for message", // tp_doc
- 0, // tp_traverse
- 0, // tp_clear
- 0, // tp_richcompare
- 0, // tp_weaklistoffset
- message_map_container::GetIterator, // tp_iter
- 0, // tp_iternext
- message_map_container::Methods, // tp_methods
- 0, // tp_members
- 0, // tp_getset
- 0, // tp_base
- 0, // tp_dict
- 0, // tp_descr_get
- 0, // tp_descr_set
- 0, // tp_dictoffset
- 0, // tp_init
-};
+#if PY_MAJOR_VERSION >= 3
+ static PyType_Slot MessageMapContainer_Type_slots[] = {
+ {Py_tp_dealloc, (void *)message_map_container::Dealloc},
+ {Py_mp_length, (void *)message_map_container::Length},
+ {Py_mp_subscript, (void *)message_map_container::GetItem},
+ {Py_mp_ass_subscript, (void *)message_map_container::SetItem},
+ {Py_tp_methods, (void *)message_map_container::Methods},
+ {Py_tp_iter, (void *)message_map_container::GetIterator},
+ {0, 0}
+ };
+
+ PyType_Spec MessageMapContainer_Type_spec = {
+ FULL_MODULE_NAME ".MessageMapContainer",
+ sizeof(MessageMapContainer),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ MessageMapContainer_Type_slots
+ };
+
+ PyObject *MessageMapContainer_Type;
+
+#else
+ PyTypeObject MessageMapContainer_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ FULL_MODULE_NAME ".MessageMapContainer", // tp_name
+ sizeof(MessageMapContainer), // tp_basicsize
+ 0, // tp_itemsize
+ message_map_container::Dealloc, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ &message_map_container::MpMethods, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ "A map container for message", // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ message_map_container::GetIterator, // tp_iter
+ 0, // tp_iternext
+ message_map_container::Methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ };
+#endif
PyTypeObject MessageMapIterator_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
diff --git a/python/google/protobuf/pyext/message_map_container.h b/python/google/protobuf/pyext/message_map_container.h
index 4ca0aecc..8286ba8a 100644
--- a/python/google/protobuf/pyext/message_map_container.h
+++ b/python/google/protobuf/pyext/message_map_container.h
@@ -89,7 +89,12 @@ struct MessageMapContainer {
uint64 version;
};
-extern PyTypeObject MessageMapContainer_Type;
+#if PY_MAJOR_VERSION >= 3
+ extern PyObject *MessageMapContainer_Type;
+ extern PyType_Spec MessageMapContainer_Type_spec;
+#else
+ extern PyTypeObject MessageMapContainer_Type;
+#endif
extern PyTypeObject MessageMapIterator_Type;
namespace message_map_container {
diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc
index 86b75d0f..fe2e600b 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.cc
+++ b/python/google/protobuf/pyext/repeated_composite_container.cc
@@ -38,11 +38,13 @@
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/message.h>
#include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
#include <google/protobuf/pyext/message.h>
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
@@ -74,125 +76,6 @@ namespace repeated_composite_container {
GOOGLE_CHECK((self)->parent == NULL); \
} while (0);
-// Returns a new reference.
-static PyObject* GetKey(PyObject* x) {
- // Just the identity function.
- Py_INCREF(x);
- return x;
-}
-
-#define GET_KEY(keyfunc, value) \
- ((keyfunc) == NULL ? \
- GetKey((value)) : \
- PyObject_CallFunctionObjArgs((keyfunc), (value), NULL))
-
-// Converts a comparison function that returns -1, 0, or 1 into a
-// less-than predicate.
-//
-// Returns -1 on error, 1 if x < y, 0 if x >= y.
-static int islt(PyObject *x, PyObject *y, PyObject *compare) {
- if (compare == NULL)
- return PyObject_RichCompareBool(x, y, Py_LT);
-
- ScopedPyObjectPtr res(PyObject_CallFunctionObjArgs(compare, x, y, NULL));
- if (res == NULL)
- return -1;
- if (!PyInt_Check(res)) {
- PyErr_Format(PyExc_TypeError,
- "comparison function must return int, not %.200s",
- Py_TYPE(res)->tp_name);
- return -1;
- }
- return PyInt_AsLong(res) < 0;
-}
-
-// Copied from uarrsort.c but swaps memcpy swaps with protobuf/python swaps
-// TODO(anuraag): Is there a better way to do this then reinventing the wheel?
-static int InternalQuickSort(RepeatedCompositeContainer* self,
- Py_ssize_t start,
- Py_ssize_t limit,
- PyObject* cmp,
- PyObject* keyfunc) {
- if (limit - start <= 1)
- return 0; // Nothing to sort.
-
- GOOGLE_CHECK_ATTACHED(self);
-
- Message* message = self->message;
- const Reflection* reflection = message->GetReflection();
- const FieldDescriptor* descriptor = self->parent_field_descriptor;
- Py_ssize_t left;
- Py_ssize_t right;
-
- PyObject* children = self->child_messages;
-
- do {
- left = start;
- right = limit;
- ScopedPyObjectPtr mid(
- GET_KEY(keyfunc, PyList_GET_ITEM(children, (start + limit) / 2)));
- do {
- ScopedPyObjectPtr key(GET_KEY(keyfunc, PyList_GET_ITEM(children, left)));
- int is_lt = islt(key, mid, cmp);
- if (is_lt == -1)
- return -1;
- /* array[left]<x */
- while (is_lt) {
- ++left;
- ScopedPyObjectPtr key(GET_KEY(keyfunc,
- PyList_GET_ITEM(children, left)));
- is_lt = islt(key, mid, cmp);
- if (is_lt == -1)
- return -1;
- }
- key.reset(GET_KEY(keyfunc, PyList_GET_ITEM(children, right - 1)));
- is_lt = islt(mid, key, cmp);
- if (is_lt == -1)
- return -1;
- while (is_lt) {
- --right;
- ScopedPyObjectPtr key(GET_KEY(keyfunc,
- PyList_GET_ITEM(children, right - 1)));
- is_lt = islt(mid, key, cmp);
- if (is_lt == -1)
- return -1;
- }
- if (left < right) {
- --right;
- if (left < right) {
- reflection->SwapElements(message, descriptor, left, right);
- PyObject* tmp = PyList_GET_ITEM(children, left);
- PyList_SET_ITEM(children, left, PyList_GET_ITEM(children, right));
- PyList_SET_ITEM(children, right, tmp);
- }
- ++left;
- }
- } while (left < right);
-
- if ((right - start) < (limit - left)) {
- /* sort [start..right[ */
- if (start < (right - 1)) {
- InternalQuickSort(self, start, right, cmp, keyfunc);
- }
-
- /* sort [left..limit[ */
- start = left;
- } else {
- /* sort [left..limit[ */
- if (left < (limit - 1)) {
- InternalQuickSort(self, left, limit, cmp, keyfunc);
- }
-
- /* sort [start..right[ */
- limit = right;
- }
- } while (start < (limit - 1));
-
- return 0;
-}
-
-#undef GET_KEY
-
// ---------------------------------------------------------------------
// len()
@@ -329,7 +212,7 @@ PyObject* Extend(RepeatedCompositeContainer* self, PyObject* value) {
return NULL;
}
CMessage* new_cmessage = reinterpret_cast<CMessage*>(new_message.get());
- if (cmessage::MergeFrom(new_cmessage, next) == NULL) {
+ if (ScopedPyObjectPtr(cmessage::MergeFrom(new_cmessage, next)) == NULL) {
return NULL;
}
}
@@ -455,58 +338,39 @@ static PyObject* RichCompare(RepeatedCompositeContainer* self,
// ---------------------------------------------------------------------
// sort()
-static PyObject* SortAttached(RepeatedCompositeContainer* self,
- PyObject* args,
- PyObject* kwds) {
- // Sort the underlying Message array.
- PyObject *compare = NULL;
- int reverse = 0;
- PyObject *keyfunc = NULL;
- static char *kwlist[] = {"cmp", "key", "reverse", 0};
-
- if (args != NULL) {
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi:sort",
- kwlist, &compare, &keyfunc, &reverse))
- return NULL;
- }
- if (compare == Py_None)
- compare = NULL;
- if (keyfunc == Py_None)
- keyfunc = NULL;
-
+static void ReorderAttached(RepeatedCompositeContainer* self) {
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
+ const FieldDescriptor* descriptor = self->parent_field_descriptor;
const Py_ssize_t length = Length(self);
- if (InternalQuickSort(self, 0, length, compare, keyfunc) < 0)
- return NULL;
-
- // Finally reverse the result if requested.
- if (reverse) {
- Message* message = self->message;
- const Reflection* reflection = message->GetReflection();
- const FieldDescriptor* descriptor = self->parent_field_descriptor;
- // Reverse the Message array.
- for (int i = 0; i < length / 2; ++i)
- reflection->SwapElements(message, descriptor, i, length - i - 1);
+ // Since Python protobuf objects are never arena-allocated, adding and
+ // removing message pointers to the underlying array is just updating
+ // pointers.
+ for (Py_ssize_t i = 0; i < length; ++i)
+ reflection->ReleaseLast(message, descriptor);
- // Reverse the Python list.
- ScopedPyObjectPtr res(PyObject_CallMethod(self->child_messages,
- "reverse", NULL));
- if (res == NULL)
- return NULL;
+ for (Py_ssize_t i = 0; i < length; ++i) {
+ CMessage* py_cmsg = reinterpret_cast<CMessage*>(
+ PyList_GET_ITEM(self->child_messages, i));
+ reflection->AddAllocatedMessage(message, descriptor, py_cmsg->message);
}
-
- Py_RETURN_NONE;
}
-static PyObject* SortReleased(RepeatedCompositeContainer* self,
- PyObject* args,
- PyObject* kwds) {
+// Returns 0 if successful; returns -1 and sets an exception if
+// unsuccessful.
+static int SortPythonMessages(RepeatedCompositeContainer* self,
+ PyObject* args,
+ PyObject* kwds) {
ScopedPyObjectPtr m(PyObject_GetAttrString(self->child_messages, "sort"));
if (m == NULL)
- return NULL;
+ return -1;
if (PyObject_Call(m, args, kwds) == NULL)
- return NULL;
- Py_RETURN_NONE;
+ return -1;
+ if (self->message != NULL) {
+ ReorderAttached(self);
+ }
+ return 0;
}
static PyObject* Sort(RepeatedCompositeContainer* self,
@@ -527,11 +391,10 @@ static PyObject* Sort(RepeatedCompositeContainer* self,
if (UpdateChildMessages(self) < 0) {
return NULL;
}
- if (self->message == NULL) {
- return SortReleased(self, args, kwds);
- } else {
- return SortAttached(self, args, kwds);
+ if (SortPythonMessages(self, args, kwds) < 0) {
+ return NULL;
}
+ Py_RETURN_NONE;
}
// ---------------------------------------------------------------------
@@ -584,18 +447,6 @@ void ReleaseLastTo(CMessage* parent,
parent->message->GetReflection()->ReleaseLast(parent->message, field));
// TODO(tibell): Deal with proto1.
- // ReleaseMessage will return NULL which differs from
- // child_cmessage->message, if the field does not exist. In this case,
- // the latter points to the default instance via a const_cast<>, so we
- // have to reset it to a new mutable object since we are taking ownership.
- if (released_message.get() == NULL) {
- const Message* prototype =
- cmessage::GetMessageFactory()->GetPrototype(
- target->message->GetDescriptor());
- GOOGLE_CHECK_NOTNULL(prototype);
- released_message.reset(prototype->New());
- }
-
target->parent = NULL;
target->parent_field_descriptor = NULL;
target->message = released_message.get();
@@ -732,7 +583,7 @@ PyTypeObject RepeatedCompositeContainer_Type = {
0, // tp_as_number
&repeated_composite_container::SqMethods, // tp_as_sequence
&repeated_composite_container::MpMethods, // tp_as_mapping
- 0, // tp_hash
+ PyObject_HashNotImplemented, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc
index fd196836..7565c6fd 100644
--- a/python/google/protobuf/pyext/repeated_scalar_container.cc
+++ b/python/google/protobuf/pyext/repeated_scalar_container.cc
@@ -39,10 +39,12 @@
#endif
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/message.h>
#include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
#include <google/protobuf/pyext/message.h>
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
@@ -68,7 +70,7 @@ static int InternalAssignRepeatedField(
self->parent_field_descriptor);
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(list); ++i) {
PyObject* value = PyList_GET_ITEM(list, i);
- if (Append(self, value) == NULL) {
+ if (ScopedPyObjectPtr(Append(self, value)) == NULL) {
return -1;
}
}
@@ -510,7 +512,7 @@ PyObject* Extend(RepeatedScalarContainer* self, PyObject* value) {
}
ScopedPyObjectPtr next;
while ((next.reset(PyIter_Next(iter))) != NULL) {
- if (Append(self, next) == NULL) {
+ if (ScopedPyObjectPtr(Append(self, next)) == NULL) {
return NULL;
}
}
@@ -690,8 +692,7 @@ static int InitializeAndCopyToParentContainer(
if (values == NULL) {
return -1;
}
- Message* new_message = cmessage::GetMessageFactory()->GetPrototype(
- from->message->GetDescriptor())->New();
+ Message* new_message = from->message->New();
to->parent = NULL;
to->parent_field_descriptor = from->parent_field_descriptor;
to->message = new_message;
@@ -781,7 +782,7 @@ PyTypeObject RepeatedScalarContainer_Type = {
0, // tp_as_number
&repeated_scalar_container::SqMethods, // tp_as_sequence
&repeated_scalar_container::MpMethods, // tp_as_mapping
- 0, // tp_hash
+ PyObject_HashNotImplemented, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
diff --git a/python/google/protobuf/pyext/scalar_map_container.cc b/python/google/protobuf/pyext/scalar_map_container.cc
index 6f731d27..a355edb2 100644
--- a/python/google/protobuf/pyext/scalar_map_container.cc
+++ b/python/google/protobuf/pyext/scalar_map_container.cc
@@ -32,6 +32,7 @@
#include <google/protobuf/pyext/scalar_map_container.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/message.h>
#include <google/protobuf/pyext/message.h>
@@ -82,7 +83,12 @@ PyObject *NewContainer(
return NULL;
}
+#if PY_MAJOR_VERSION >= 3
+ ScopedPyObjectPtr obj(PyType_GenericAlloc(
+ reinterpret_cast<PyTypeObject *>(ScalarMapContainer_Type), 0));
+#else
ScopedPyObjectPtr obj(PyType_GenericAlloc(&ScalarMapContainer_Type, 0));
+#endif
if (obj.get() == NULL) {
return PyErr_Format(PyExc_RuntimeError,
"Could not allocate new container.");
@@ -431,44 +437,66 @@ PyObject* IterNext(PyObject* _self) {
} // namespace scalar_map_iterator
-PyTypeObject ScalarMapContainer_Type = {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
- FULL_MODULE_NAME ".ScalarMapContainer", // tp_name
- sizeof(ScalarMapContainer), // tp_basicsize
- 0, // tp_itemsize
- scalar_map_container::Dealloc, // tp_dealloc
- 0, // tp_print
- 0, // tp_getattr
- 0, // tp_setattr
- 0, // tp_compare
- 0, // tp_repr
- 0, // tp_as_number
- 0, // tp_as_sequence
- &scalar_map_container::MpMethods, // tp_as_mapping
- 0, // tp_hash
- 0, // tp_call
- 0, // tp_str
- 0, // tp_getattro
- 0, // tp_setattro
- 0, // tp_as_buffer
- Py_TPFLAGS_DEFAULT, // tp_flags
- "A scalar map container", // tp_doc
- 0, // tp_traverse
- 0, // tp_clear
- 0, // tp_richcompare
- 0, // tp_weaklistoffset
- scalar_map_container::GetIterator, // tp_iter
- 0, // tp_iternext
- scalar_map_container::Methods, // tp_methods
- 0, // tp_members
- 0, // tp_getset
- 0, // tp_base
- 0, // tp_dict
- 0, // tp_descr_get
- 0, // tp_descr_set
- 0, // tp_dictoffset
- 0, // tp_init
-};
+
+#if PY_MAJOR_VERSION >= 3
+ static PyType_Slot ScalarMapContainer_Type_slots[] = {
+ {Py_tp_dealloc, (void *)scalar_map_container::Dealloc},
+ {Py_mp_length, (void *)scalar_map_container::Length},
+ {Py_mp_subscript, (void *)scalar_map_container::GetItem},
+ {Py_mp_ass_subscript, (void *)scalar_map_container::SetItem},
+ {Py_tp_methods, (void *)scalar_map_container::Methods},
+ {Py_tp_iter, (void *)scalar_map_container::GetIterator},
+ {0, 0},
+ };
+
+ PyType_Spec ScalarMapContainer_Type_spec = {
+ FULL_MODULE_NAME ".ScalarMapContainer",
+ sizeof(ScalarMapContainer),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ ScalarMapContainer_Type_slots
+ };
+ PyObject *ScalarMapContainer_Type;
+#else
+ PyTypeObject ScalarMapContainer_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ FULL_MODULE_NAME ".ScalarMapContainer", // tp_name
+ sizeof(ScalarMapContainer), // tp_basicsize
+ 0, // tp_itemsize
+ scalar_map_container::Dealloc, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ &scalar_map_container::MpMethods, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ "A scalar map container", // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ scalar_map_container::GetIterator, // tp_iter
+ 0, // tp_iternext
+ scalar_map_container::Methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ };
+#endif
PyTypeObject ScalarMapIterator_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
diff --git a/python/google/protobuf/pyext/scalar_map_container.h b/python/google/protobuf/pyext/scalar_map_container.h
index 254e6e98..aded8d49 100644
--- a/python/google/protobuf/pyext/scalar_map_container.h
+++ b/python/google/protobuf/pyext/scalar_map_container.h
@@ -83,7 +83,12 @@ struct ScalarMapContainer {
uint64 version;
};
-extern PyTypeObject ScalarMapContainer_Type;
+#if PY_MAJOR_VERSION >= 3
+ extern PyObject *ScalarMapContainer_Type;
+ extern PyType_Spec ScalarMapContainer_Type_spec;
+#else
+ extern PyTypeObject ScalarMapContainer_Type;
+#endif
extern PyTypeObject ScalarMapIterator_Type;
namespace scalar_map_container {
diff --git a/python/google/protobuf/pyext/scoped_pyobject_ptr.h b/python/google/protobuf/pyext/scoped_pyobject_ptr.h
index 18ddd5cd..9979b83b 100644
--- a/python/google/protobuf/pyext/scoped_pyobject_ptr.h
+++ b/python/google/protobuf/pyext/scoped_pyobject_ptr.h
@@ -51,16 +51,22 @@ class ScopedPyObjectPtr {
// Reset. Deletes the current owned object, if any.
// Then takes ownership of a new object, if given.
- // this->reset(this->get()) works.
+ // This function must be called with a reference that you own.
+ // this->reset(this->get()) is wrong!
+ // this->reset(this->release()) is OK.
PyObject* reset(PyObject* p = NULL) {
- if (p != ptr_) {
- Py_XDECREF(ptr_);
- ptr_ = p;
- }
+ Py_XDECREF(ptr_);
+ ptr_ = p;
return ptr_;
}
+ // ScopedPyObjectPtr should not be copied.
+ // We explicitly list and delete this overload to avoid automatic conversion
+ // to PyObject*, which is wrong in this case.
+ PyObject* reset(const ScopedPyObjectPtr& other) = delete;
+
// Releases ownership of the object.
+ // The caller now owns the returned reference.
PyObject* release() {
PyObject* p = ptr_;
ptr_ = NULL;
diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py
index 82fca661..0c757264 100755
--- a/python/google/protobuf/reflection.py
+++ b/python/google/protobuf/reflection.py
@@ -49,101 +49,23 @@ __author__ = 'robinson@google.com (Will Robinson)'
from google.protobuf.internal import api_implementation
-from google.protobuf import descriptor as descriptor_mod
from google.protobuf import message
-_FieldDescriptor = descriptor_mod.FieldDescriptor
-
if api_implementation.Type() == 'cpp':
from google.protobuf.pyext import cpp_message as message_impl
else:
from google.protobuf.internal import python_message as message_impl
-_NewMessage = message_impl.NewMessage
-_InitMessage = message_impl.InitMessage
-
-
-class GeneratedProtocolMessageType(type):
-
- """Metaclass for protocol message classes created at runtime from Descriptors.
-
- We add implementations for all methods described in the Message class. We
- also create properties to allow getting/setting all fields in the protocol
- message. Finally, we create slots to prevent users from accidentally
- "setting" nonexistent fields in the protocol message, which then wouldn't get
- serialized / deserialized properly.
-
- The protocol compiler currently uses this metaclass to create protocol
- message classes at runtime. Clients can also manually create their own
- classes at runtime, as in this example:
-
- mydescriptor = Descriptor(.....)
- class MyProtoClass(Message):
- __metaclass__ = GeneratedProtocolMessageType
- DESCRIPTOR = mydescriptor
- myproto_instance = MyProtoClass()
- myproto.foo_field = 23
- ...
-
- The above example will not work for nested types. If you wish to include them,
- use reflection.MakeClass() instead of manually instantiating the class in
- order to create the appropriate class structure.
- """
-
- # Must be consistent with the protocol-compiler code in
- # proto2/compiler/internal/generator.*.
- _DESCRIPTOR_KEY = 'DESCRIPTOR'
-
- def __new__(cls, name, bases, dictionary):
- """Custom allocation for runtime-generated class types.
-
- We override __new__ because this is apparently the only place
- where we can meaningfully set __slots__ on the class we're creating(?).
- (The interplay between metaclasses and slots is not very well-documented).
-
- Args:
- name: Name of the class (ignored, but required by the
- metaclass protocol).
- bases: Base classes of the class we're constructing.
- (Should be message.Message). We ignore this field, but
- it's required by the metaclass protocol
- dictionary: The class dictionary of the class we're
- constructing. dictionary[_DESCRIPTOR_KEY] must contain
- a Descriptor object describing this protocol message
- type.
-
- Returns:
- Newly-allocated class.
- """
- descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
- bases = _NewMessage(bases, descriptor, dictionary)
- superclass = super(GeneratedProtocolMessageType, cls)
-
- new_class = superclass.__new__(cls, name, bases, dictionary)
- return new_class
-
- def __init__(cls, name, bases, dictionary):
- """Here we perform the majority of our work on the class.
- We add enum getters, an __init__ method, implementations
- of all Message methods, and properties for all fields
- in the protocol type.
-
- Args:
- name: Name of the class (ignored, but required by the
- metaclass protocol).
- bases: Base classes of the class we're constructing.
- (Should be message.Message). We ignore this field, but
- it's required by the metaclass protocol
- dictionary: The class dictionary of the class we're
- constructing. dictionary[_DESCRIPTOR_KEY] must contain
- a Descriptor object describing this protocol message
- type.
- """
- descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
- _InitMessage(descriptor, cls)
- superclass = super(GeneratedProtocolMessageType, cls)
- superclass.__init__(name, bases, dictionary)
+# The type of all Message classes.
+# Part of the public interface.
+#
+# Used by generated files, but clients can also use it at runtime:
+# mydescriptor = pool.FindDescriptor(.....)
+# class MyProtoClass(Message):
+# __metaclass__ = GeneratedProtocolMessageType
+# DESCRIPTOR = mydescriptor
+GeneratedProtocolMessageType = message_impl.GeneratedProtocolMessageType
def ParseMessage(descriptor, byte_str):
diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py
index 145bb656..1399223f 100755
--- a/python/google/protobuf/text_format.py
+++ b/python/google/protobuf/text_format.py
@@ -135,7 +135,7 @@ def PrintMessage(message, out, indent=0, as_utf8=False, as_one_line=False,
fields.sort(key=lambda x: x[0].index)
for field, value in fields:
if _IsMapEntry(field):
- for key in value:
+ 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.
diff --git a/python/setup.py b/python/setup.py
index f7ee6357..8269c4a5 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -77,11 +77,15 @@ def generate_proto(source, require = True):
def GenerateUnittestProtos():
generate_proto("../src/google/protobuf/map_unittest.proto", False)
+ generate_proto("../src/google/protobuf/unittest_arena.proto", False)
+ generate_proto("../src/google/protobuf/unittest_no_arena.proto", False)
+ generate_proto("../src/google/protobuf/unittest_no_arena_import.proto", False)
generate_proto("../src/google/protobuf/unittest.proto", False)
generate_proto("../src/google/protobuf/unittest_custom_options.proto", False)
generate_proto("../src/google/protobuf/unittest_import.proto", False)
generate_proto("../src/google/protobuf/unittest_import_public.proto", False)
generate_proto("../src/google/protobuf/unittest_mset.proto", False)
+ generate_proto("../src/google/protobuf/unittest_mset_wire_format.proto", False)
generate_proto("../src/google/protobuf/unittest_no_generic_services.proto", False)
generate_proto("../src/google/protobuf/unittest_proto3_arena.proto", False)
generate_proto("google/protobuf/internal/descriptor_pool_test1.proto", False)
@@ -91,9 +95,11 @@ def GenerateUnittestProtos():
generate_proto("google/protobuf/internal/import_test_package/inner.proto", False)
generate_proto("google/protobuf/internal/import_test_package/outer.proto", False)
generate_proto("google/protobuf/internal/missing_enum_values.proto", False)
+ generate_proto("google/protobuf/internal/message_set_extensions.proto", False)
generate_proto("google/protobuf/internal/more_extensions.proto", False)
generate_proto("google/protobuf/internal/more_extensions_dynamic.proto", False)
generate_proto("google/protobuf/internal/more_messages.proto", False)
+ generate_proto("google/protobuf/internal/packed_field_test.proto", False)
generate_proto("google/protobuf/internal/test_bad_identifiers.proto", False)
generate_proto("google/protobuf/pyext/python.proto", False)
diff --git a/python/tox.ini b/python/tox.ini
index d0100758..a6352ef4 100644
--- a/python/tox.ini
+++ b/python/tox.ini
@@ -2,8 +2,7 @@
envlist =
# cpp implementation on py34 is currently broken due to
# changes introduced by http://bugs.python.org/issue22079.
- #py{26,27,33,34}-{cpp,python}
- py{26,27,33}-{cpp,python}, py34-{python}
+ py{26,27,33,34}-{cpp,python}
[testenv]
usedevelop=true
diff --git a/ruby/Gemfile.lock b/ruby/Gemfile.lock
index 2cf5e472..91e1666f 100644
--- a/ruby/Gemfile.lock
+++ b/ruby/Gemfile.lock
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
- google-protobuf (3.0.0.alpha.3)
+ google-protobuf (3.0.0.alpha.4)
GEM
remote: https://rubygems.org/
diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec
index a9e570ec..3d53209d 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.4.0.pre"
+ s.version = "3.0.0.alpha.4.0"
s.licenses = ["BSD"]
s.summary = "Protocol Buffers"
s.description = "Protocol Buffers are Google's data interchange format."
diff --git a/ruby/pom.xml b/ruby/pom.xml
index 247b243a..4cbd6d30 100644
--- a/ruby/pom.xml
+++ b/ruby/pom.xml
@@ -86,7 +86,7 @@
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
- <version>3.0.0-alpha-2</version>
+ <version>3.0.0-alpha-3</version>
</dependency>
</dependencies>
</project>
diff --git a/src/Makefile.am b/src/Makefile.am
index 584bcd21..caae2933 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -158,9 +158,11 @@ nobase_include_HEADERS = \
google/protobuf/compiler/csharp/csharp_generator.h \
google/protobuf/compiler/csharp/csharp_names.h \
google/protobuf/util/type_resolver.h \
- google/protobuf/util/type_resolver_util.h \
- google/protobuf/util/json_util.h \
google/protobuf/util/field_comparator.h \
+ google/protobuf/util/field_mask_util.h \
+ google/protobuf/util/json_util.h \
+ google/protobuf/util/time_util.h \
+ google/protobuf/util/type_resolver_util.h \
google/protobuf/util/message_differencer.h
lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la
@@ -174,6 +176,8 @@ libprotobuf_lite_la_SOURCES = \
google/protobuf/stubs/bytestream.h \
google/protobuf/stubs/common.cc \
google/protobuf/stubs/hash.h \
+ google/protobuf/stubs/int128.cc \
+ google/protobuf/stubs/int128.h \
google/protobuf/stubs/map_util.h \
google/protobuf/stubs/mathutil.h \
google/protobuf/stubs/once.cc \
@@ -187,6 +191,7 @@ libprotobuf_lite_la_SOURCES = \
google/protobuf/stubs/stringpiece.h \
google/protobuf/stubs/stringprintf.cc \
google/protobuf/stubs/stringprintf.h \
+ google/protobuf/stubs/structurally_valid.cc \
google/protobuf/stubs/strutil.cc \
google/protobuf/stubs/strutil.h \
google/protobuf/stubs/time.cc \
@@ -209,8 +214,8 @@ libprotobuf_la_SOURCES = \
$(libprotobuf_lite_la_SOURCES) \
google/protobuf/any.pb.cc \
google/protobuf/api.pb.cc \
- google/protobuf/stubs/mathlimits.h \
google/protobuf/stubs/mathlimits.cc \
+ google/protobuf/stubs/mathlimits.h \
google/protobuf/any.cc \
google/protobuf/descriptor.cc \
google/protobuf/descriptor_database.cc \
@@ -228,7 +233,6 @@ libprotobuf_la_SOURCES = \
google/protobuf/service.cc \
google/protobuf/source_context.pb.cc \
google/protobuf/struct.pb.cc \
- google/protobuf/stubs/structurally_valid.cc \
google/protobuf/stubs/substitute.cc \
google/protobuf/stubs/substitute.h \
google/protobuf/text_format.cc \
@@ -245,6 +249,7 @@ libprotobuf_la_SOURCES = \
google/protobuf/compiler/importer.cc \
google/protobuf/compiler/parser.cc \
google/protobuf/util/field_comparator.cc \
+ google/protobuf/util/field_mask_util.cc \
google/protobuf/util/internal/constants.h \
google/protobuf/util/internal/datapiece.cc \
google/protobuf/util/internal/datapiece.h \
@@ -281,8 +286,10 @@ libprotobuf_la_SOURCES = \
google/protobuf/util/internal/utility.cc \
google/protobuf/util/internal/utility.h \
google/protobuf/util/json_util.cc \
- google/protobuf/util/type_resolver_util.cc \
- google/protobuf/util/message_differencer.cc
+ google/protobuf/util/message_differencer.cc \
+ google/protobuf/util/time_util.cc \
+ google/protobuf/util/type_resolver_util.cc
+
nodist_libprotobuf_la_SOURCES = $(nodist_libprotobuf_lite_la_SOURCES)
libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la
@@ -325,11 +332,13 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/java/java_context.cc \
google/protobuf/compiler/java/java_context.h \
google/protobuf/compiler/java/java_enum.cc \
+ google/protobuf/compiler/java/java_enum_lite.cc \
google/protobuf/compiler/java/java_enum_field.cc \
google/protobuf/compiler/java/java_enum_field.h \
google/protobuf/compiler/java/java_enum_field_lite.cc \
google/protobuf/compiler/java/java_enum_field_lite.h \
google/protobuf/compiler/java/java_enum.h \
+ google/protobuf/compiler/java/java_enum_lite.h \
google/protobuf/compiler/java/java_extension.cc \
google/protobuf/compiler/java/java_extension.h \
google/protobuf/compiler/java/java_field.cc \
@@ -480,6 +489,8 @@ protoc_inputs = \
google/protobuf/unittest_lite_imports_nonlite.proto \
google/protobuf/unittest_lite.proto \
google/protobuf/unittest_mset.proto \
+ google/protobuf/unittest_mset_wire_format.proto \
+ google/protobuf/unittest_no_arena_lite.proto \
google/protobuf/unittest_no_arena_import.proto \
google/protobuf/unittest_no_arena.proto \
google/protobuf/unittest_no_field_presence.proto \
@@ -496,6 +507,7 @@ protoc_inputs = \
google/protobuf/util/internal/testdata/default_value_test.proto \
google/protobuf/util/internal/testdata/field_mask.proto \
google/protobuf/util/internal/testdata/maps.proto \
+ google/protobuf/util/internal/testdata/oneofs.proto \
google/protobuf/util/internal/testdata/struct.proto \
google/protobuf/util/internal/testdata/timestamp_duration.proto \
google/protobuf/util/json_format_proto3.proto \
@@ -530,6 +542,8 @@ protoc_lite_outputs = \
google/protobuf/map_lite_unittest.pb.h \
google/protobuf/unittest_lite.pb.cc \
google/protobuf/unittest_lite.pb.h \
+ google/protobuf/unittest_no_arena_lite.pb.cc \
+ google/protobuf/unittest_no_arena_lite.pb.h \
google/protobuf/unittest_import_lite.pb.cc \
google/protobuf/unittest_import_lite.pb.h \
google/protobuf/unittest_import_public_lite.pb.cc \
@@ -567,6 +581,8 @@ protoc_outputs = \
google/protobuf/unittest_lite_imports_nonlite.pb.h \
google/protobuf/unittest_mset.pb.cc \
google/protobuf/unittest_mset.pb.h \
+ google/protobuf/unittest_mset_wire_format.pb.cc \
+ google/protobuf/unittest_mset_wire_format.pb.h \
google/protobuf/unittest_no_arena_import.pb.cc \
google/protobuf/unittest_no_arena_import.pb.h \
google/protobuf/unittest_no_arena.pb.cc \
@@ -599,6 +615,8 @@ protoc_outputs = \
google/protobuf/util/internal/testdata/field_mask.pb.h \
google/protobuf/util/internal/testdata/maps.pb.cc \
google/protobuf/util/internal/testdata/maps.pb.h \
+ google/protobuf/util/internal/testdata/oneofs.pb.cc \
+ google/protobuf/util/internal/testdata/oneofs.pb.h \
google/protobuf/util/internal/testdata/struct.pb.cc \
google/protobuf/util/internal/testdata/struct.pb.h \
google/protobuf/util/internal/testdata/timestamp_duration.pb.cc \
@@ -641,7 +659,8 @@ COMMON_TEST_SOURCES = \
google/protobuf/testing/file.h
check_PROGRAMS = protoc protobuf-test protobuf-lazy-descriptor-test \
- protobuf-lite-test test_plugin $(GZCHECKPROGRAMS)
+ protobuf-lite-test test_plugin protobuf-lite-arena-test \
+ $(GZCHECKPROGRAMS)
protobuf_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \
../gmock/gtest/lib/libgtest.la \
../gmock/lib/libgmock.la \
@@ -655,6 +674,7 @@ protobuf_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
protobuf_test_SOURCES = \
google/protobuf/stubs/bytestream_unittest.cc \
google/protobuf/stubs/common_unittest.cc \
+ google/protobuf/stubs/int128_unittest.cc \
google/protobuf/stubs/once_unittest.cc \
google/protobuf/stubs/statusor_test.cc \
google/protobuf/stubs/status_test.cc \
@@ -707,6 +727,7 @@ protobuf_test_SOURCES = \
google/protobuf/compiler/ruby/ruby_generator_unittest.cc \
google/protobuf/compiler/csharp/csharp_generator_unittest.cc \
google/protobuf/util/field_comparator_test.cc \
+ google/protobuf/util/field_mask_util_test.cc \
google/protobuf/util/internal/default_value_objectwriter_test.cc \
google/protobuf/util/internal/json_objectwriter_test.cc \
google/protobuf/util/internal/json_stream_parser_test.cc \
@@ -714,6 +735,7 @@ protobuf_test_SOURCES = \
google/protobuf/util/internal/protostream_objectwriter_test.cc \
google/protobuf/util/internal/type_info_test_helper.cc \
google/protobuf/util/json_util_test.cc \
+ google/protobuf/util/time_util_test.cc \
google/protobuf/util/type_resolver_util_test.cc \
$(COMMON_TEST_SOURCES)
@@ -735,21 +757,40 @@ protobuf_lazy_descriptor_test_SOURCES = \
$(COMMON_TEST_SOURCES)
nodist_protobuf_lazy_descriptor_test_SOURCES = $(protoc_outputs)
-# Build lite_unittest separately, since it doesn't use gtest.
-protobuf_lite_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la
-protobuf_lite_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
-protobuf_lite_test_SOURCES = \
+COMMON_LITE_TEST_SOURCES = \
google/protobuf/arena_test_util.cc \
google/protobuf/arena_test_util.h \
- google/protobuf/lite_unittest.cc \
google/protobuf/map_lite_test_util.cc \
google/protobuf/map_lite_test_util.h \
google/protobuf/test_util_lite.cc \
google/protobuf/test_util_lite.h
- # TODO(teboring) add the file back and make the test build.
- # google/protobuf/map_lite_test.cc
+
+# Build lite_unittest separately, since it doesn't use gtest. It can't
+# depend on gtest because our internal version of gtest depend on proto
+# full runtime and we want to make sure this test builds without full
+# runtime.
+protobuf_lite_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la
+protobuf_lite_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
+protobuf_lite_test_SOURCES = \
+ google/protobuf/lite_unittest.cc \
+ $(COMMON_LITE_TEST_SOURCES)
nodist_protobuf_lite_test_SOURCES = $(protoc_lite_outputs)
+# lite_arena_unittest depends on gtest because teboring@ found that without
+# gtest when building the test internally our memory sanitizer doesn't detect
+# memory leaks (don't know why).
+protobuf_lite_arena_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la \
+ ../gmock/gtest/lib/libgtest.la \
+ ../gmock/lib/libgmock.la \
+ ../gmock/lib/libgmock_main.la
+protobuf_lite_arena_test_CPPFLAGS = -I$(srcdir)/../gmock/include \
+ -I$(srcdir)/../gmock/gtest/include
+protobuf_lite_arena_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
+protobuf_lite_arena_test_SOURCES = \
+ google/protobuf/lite_arena_unittest.cc \
+ $(COMMON_LITE_TEST_SOURCES)
+nodist_protobuf_lite_arena_test_SOURCES = $(protoc_lite_outputs)
+
# Test plugin binary.
test_plugin_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \
../gmock/gtest/lib/libgtest.la
@@ -769,4 +810,5 @@ zcgunzip_SOURCES = google/protobuf/testing/zcgunzip.cc
endif
TESTS = protobuf-test protobuf-lazy-descriptor-test protobuf-lite-test \
- google/protobuf/compiler/zip_output_unittest.sh $(GZTESTS)
+ google/protobuf/compiler/zip_output_unittest.sh $(GZTESTS) \
+ protobuf-lite-arena-test
diff --git a/src/google/protobuf/any.cc b/src/google/protobuf/any.cc
index c66fdfad..c6ed37ae 100644
--- a/src/google/protobuf/any.cc
+++ b/src/google/protobuf/any.cc
@@ -50,7 +50,7 @@ AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value)
void AnyMetadata::PackFrom(const Message& message) {
type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(),
- GetTypeUrl(message.GetDescriptor()));
+ GetTypeUrl(message.GetDescriptor()));
message.SerializeToString(value_->MutableNoArena(
&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
}
@@ -76,7 +76,7 @@ bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) {
type_url.size() - prefix_len);
return true;
}
- return true;
+ return false;
}
diff --git a/src/google/protobuf/any.h b/src/google/protobuf/any.h
index f681eceb..7eeb6b70 100644
--- a/src/google/protobuf/any.h
+++ b/src/google/protobuf/any.h
@@ -34,9 +34,9 @@
#include <string>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/arenastring.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
+#include <google/protobuf/arenastring.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc
index c2e58131..cbb5d233 100644
--- a/src/google/protobuf/any.pb.cc
+++ b/src/google/protobuf/any.pb.cc
@@ -208,10 +208,10 @@ bool Any::MergePartialFromCodedStream(
if (tag == 10) {
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_type_url()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->type_url().data(), this->type_url().length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.Any.type_url");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Any.type_url"));
} else {
goto handle_unusual;
}
@@ -258,9 +258,9 @@ void Any::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_start:google.protobuf.Any)
// optional string type_url = 1;
if (this->type_url().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->type_url().data(), this->type_url().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Any.type_url");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->type_url(), output);
@@ -280,9 +280,9 @@ void Any::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any)
// optional string type_url = 1;
if (this->type_url().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->type_url().data(), this->type_url().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Any.type_url");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto
index d3ad3acc..423699be 100644
--- a/src/google/protobuf/any.proto
+++ b/src/google/protobuf/any.proto
@@ -42,10 +42,8 @@ option objc_class_prefix = "GPB";
// `Any` contains an arbitrary serialized message along with a URL
// that describes the type of the serialized message.
//
-// The proto runtimes and/or compiler will eventually
-// provide utilities to pack/unpack Any values (projected Q1/15).
-//
-// # JSON
+// JSON
+// ====
// The JSON representation of an `Any` value uses the regular
// representation of the deserialized, embedded message, with an
// additional field `@type` which contains the type URL. Example:
@@ -93,10 +91,6 @@ message Any {
// Schemas other than `http`, `https` (or the empty schema) might be
// used with implementation specific semantics.
//
- // Types originating from the `google.*` package
- // namespace should use `type.googleapis.com/full.type.name` (without
- // schema and path). A type service will eventually become available which
- // serves those URLs (projected Q2/15).
string type_url = 1;
// Must be valid serialized data of the above specified type.
diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc
index 0feddb31..0a2c4ec0 100644
--- a/src/google/protobuf/api.pb.cc
+++ b/src/google/protobuf/api.pb.cc
@@ -27,6 +27,9 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
const ::google::protobuf::Descriptor* Method_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
Method_reflection_ = NULL;
+const ::google::protobuf::Descriptor* Mixin_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ Mixin_reflection_ = NULL;
} // namespace
@@ -38,12 +41,14 @@ void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto() {
"google/protobuf/api.proto");
GOOGLE_CHECK(file != NULL);
Api_descriptor_ = file->message_type(0);
- static const int Api_offsets_[5] = {
+ static const int Api_offsets_[7] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, methods_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, options_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, version_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, source_context_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, mixins_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, syntax_),
};
Api_reflection_ =
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
@@ -57,13 +62,14 @@ void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, _internal_metadata_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, _is_default_instance_));
Method_descriptor_ = file->message_type(1);
- static const int Method_offsets_[6] = {
+ static const int Method_offsets_[7] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, request_type_url_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, request_streaming_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, response_type_url_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, response_streaming_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, options_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, syntax_),
};
Method_reflection_ =
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
@@ -76,6 +82,22 @@ void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto() {
sizeof(Method),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, _internal_metadata_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, _is_default_instance_));
+ Mixin_descriptor_ = file->message_type(2);
+ static const int Mixin_offsets_[2] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Mixin, name_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Mixin, root_),
+ };
+ Mixin_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ Mixin_descriptor_,
+ Mixin::default_instance_,
+ Mixin_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(Mixin),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Mixin, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Mixin, _is_default_instance_));
}
namespace {
@@ -92,6 +114,8 @@ void protobuf_RegisterTypes(const ::std::string&) {
Api_descriptor_, &Api::default_instance());
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
Method_descriptor_, &Method::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ Mixin_descriptor_, &Mixin::default_instance());
}
} // namespace
@@ -101,6 +125,8 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto() {
delete Api_reflection_;
delete Method::default_instance_;
delete Method_reflection_;
+ delete Mixin::default_instance_;
+ delete Mixin_reflection_;
}
void protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto() {
@@ -114,24 +140,30 @@ void protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto() {
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n\031google/protobuf/api.proto\022\017google.prot"
"obuf\032$google/protobuf/source_context.pro"
- "to\032\032google/protobuf/type.proto\"\260\001\n\003Api\022\014"
+ "to\032\032google/protobuf/type.proto\"\201\002\n\003Api\022\014"
"\n\004name\030\001 \001(\t\022(\n\007methods\030\002 \003(\0132\027.google.p"
"rotobuf.Method\022(\n\007options\030\003 \003(\0132\027.google"
".protobuf.Option\022\017\n\007version\030\004 \001(\t\0226\n\016sou"
"rce_context\030\005 \001(\0132\036.google.protobuf.Sour"
- "ceContext\"\254\001\n\006Method\022\014\n\004name\030\001 \001(\t\022\030\n\020re"
- "quest_type_url\030\002 \001(\t\022\031\n\021request_streamin"
- "g\030\003 \001(\010\022\031\n\021response_type_url\030\004 \001(\t\022\032\n\022re"
- "sponse_streaming\030\005 \001(\010\022(\n\007options\030\006 \003(\0132"
- "\027.google.protobuf.OptionBH\n\023com.google.p"
- "rotobufB\010ApiProtoP\001\242\002\003GPB\252\002\036Google.Proto"
- "buf.WellKnownTypesb\006proto3", 546);
+ "ceContext\022&\n\006mixins\030\006 \003(\0132\026.google.proto"
+ "buf.Mixin\022\'\n\006syntax\030\007 \001(\0162\027.google.proto"
+ "buf.Syntax\"\325\001\n\006Method\022\014\n\004name\030\001 \001(\t\022\030\n\020r"
+ "equest_type_url\030\002 \001(\t\022\031\n\021request_streami"
+ "ng\030\003 \001(\010\022\031\n\021response_type_url\030\004 \001(\t\022\032\n\022r"
+ "esponse_streaming\030\005 \001(\010\022(\n\007options\030\006 \003(\013"
+ "2\027.google.protobuf.Option\022\'\n\006syntax\030\007 \001("
+ "\0162\027.google.protobuf.Syntax\"#\n\005Mixin\022\014\n\004n"
+ "ame\030\001 \001(\t\022\014\n\004root\030\002 \001(\tBK\n\023com.google.pr"
+ "otobufB\010ApiProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Pro"
+ "tobuf.WellKnownTypesb\006proto3", 708);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/api.proto", &protobuf_RegisterTypes);
Api::default_instance_ = new Api();
Method::default_instance_ = new Method();
+ Mixin::default_instance_ = new Mixin();
Api::default_instance_->InitAsDefaultInstance();
Method::default_instance_->InitAsDefaultInstance();
+ Mixin::default_instance_->InitAsDefaultInstance();
::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto);
}
@@ -160,6 +192,8 @@ const int Api::kMethodsFieldNumber;
const int Api::kOptionsFieldNumber;
const int Api::kVersionFieldNumber;
const int Api::kSourceContextFieldNumber;
+const int Api::kMixinsFieldNumber;
+const int Api::kSyntaxFieldNumber;
#endif // !_MSC_VER
Api::Api()
@@ -188,6 +222,7 @@ void Api::SharedCtor() {
name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
version_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
source_context_ = NULL;
+ syntax_ = 0;
}
Api::~Api() {
@@ -233,8 +268,10 @@ void Api::Clear() {
version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
+ syntax_ = 0;
methods_.Clear();
options_.Clear();
+ mixins_.Clear();
}
bool Api::MergePartialFromCodedStream(
@@ -252,10 +289,10 @@ bool Api::MergePartialFromCodedStream(
if (tag == 10) {
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_name()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.Api.name");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Api.name"));
} else {
goto handle_unusual;
}
@@ -302,10 +339,10 @@ bool Api::MergePartialFromCodedStream(
parse_version:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_version()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->version().data(), this->version().length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.Api.version");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Api.version"));
} else {
goto handle_unusual;
}
@@ -322,6 +359,39 @@ bool Api::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
+ if (input->ExpectTag(50)) goto parse_mixins;
+ break;
+ }
+
+ // repeated .google.protobuf.Mixin mixins = 6;
+ case 6: {
+ if (tag == 50) {
+ parse_mixins:
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_mixins:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ input, add_mixins()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(50)) goto parse_loop_mixins;
+ input->UnsafeDecrementRecursionDepth();
+ if (input->ExpectTag(56)) goto parse_syntax;
+ break;
+ }
+
+ // optional .google.protobuf.Syntax syntax = 7;
+ case 7: {
+ if (tag == 56) {
+ parse_syntax:
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ set_syntax(static_cast< ::google::protobuf::Syntax >(value));
+ } else {
+ goto handle_unusual;
+ }
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -352,9 +422,9 @@ void Api::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_start:google.protobuf.Api)
// optional string name = 1;
if (this->name().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Api.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
@@ -374,9 +444,9 @@ void Api::SerializeWithCachedSizes(
// optional string version = 4;
if (this->version().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->version().data(), this->version().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Api.version");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
4, this->version(), output);
@@ -388,6 +458,18 @@ void Api::SerializeWithCachedSizes(
5, *this->source_context_, output);
}
+ // repeated .google.protobuf.Mixin mixins = 6;
+ for (unsigned int i = 0, n = this->mixins_size(); i < n; i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 6, this->mixins(i), output);
+ }
+
+ // optional .google.protobuf.Syntax syntax = 7;
+ if (this->syntax() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteEnum(
+ 7, this->syntax(), output);
+ }
+
// @@protoc_insertion_point(serialize_end:google.protobuf.Api)
}
@@ -396,9 +478,9 @@ void Api::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Api)
// optional string name = 1;
if (this->name().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Api.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
@@ -421,9 +503,9 @@ void Api::SerializeWithCachedSizes(
// optional string version = 4;
if (this->version().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->version().data(), this->version().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Api.version");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
@@ -437,6 +519,19 @@ void Api::SerializeWithCachedSizes(
5, *this->source_context_, target);
}
+ // repeated .google.protobuf.Mixin mixins = 6;
+ for (unsigned int i = 0, n = this->mixins_size(); i < n; i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 6, this->mixins(i), target);
+ }
+
+ // optional .google.protobuf.Syntax syntax = 7;
+ if (this->syntax() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+ 7, this->syntax(), target);
+ }
+
// @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Api)
return target;
}
@@ -465,6 +560,12 @@ int Api::ByteSize() const {
*this->source_context_);
}
+ // optional .google.protobuf.Syntax syntax = 7;
+ if (this->syntax() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::EnumSize(this->syntax());
+ }
+
// repeated .google.protobuf.Method methods = 2;
total_size += 1 * this->methods_size();
for (int i = 0; i < this->methods_size(); i++) {
@@ -481,6 +582,14 @@ int Api::ByteSize() const {
this->options(i));
}
+ // repeated .google.protobuf.Mixin mixins = 6;
+ total_size += 1 * this->mixins_size();
+ for (int i = 0; i < this->mixins_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->mixins(i));
+ }
+
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
@@ -503,6 +612,7 @@ void Api::MergeFrom(const Api& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
methods_.MergeFrom(from.methods_);
options_.MergeFrom(from.options_);
+ mixins_.MergeFrom(from.mixins_);
if (from.name().size() > 0) {
name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
@@ -514,6 +624,9 @@ void Api::MergeFrom(const Api& from) {
if (from.has_source_context()) {
mutable_source_context()->::google::protobuf::SourceContext::MergeFrom(from.source_context());
}
+ if (from.syntax() != 0) {
+ set_syntax(from.syntax());
+ }
}
void Api::CopyFrom(const ::google::protobuf::Message& from) {
@@ -543,6 +656,8 @@ void Api::InternalSwap(Api* other) {
options_.UnsafeArenaSwap(&other->options_);
version_.Swap(&other->version_);
std::swap(source_context_, other->source_context_);
+ mixins_.UnsafeArenaSwap(&other->mixins_);
+ std::swap(syntax_, other->syntax_);
_internal_metadata_.Swap(&other->_internal_metadata_);
std::swap(_cached_size_, other->_cached_size_);
}
@@ -608,28 +723,28 @@ int Api::methods_size() const {
void Api::clear_methods() {
methods_.Clear();
}
- const ::google::protobuf::Method& Api::methods(int index) const {
+const ::google::protobuf::Method& Api::methods(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.Api.methods)
return methods_.Get(index);
}
- ::google::protobuf::Method* Api::mutable_methods(int index) {
+::google::protobuf::Method* Api::mutable_methods(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.Api.methods)
return methods_.Mutable(index);
}
- ::google::protobuf::Method* Api::add_methods() {
+::google::protobuf::Method* Api::add_methods() {
// @@protoc_insertion_point(field_add:google.protobuf.Api.methods)
return methods_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >&
-Api::methods() const {
- // @@protoc_insertion_point(field_list:google.protobuf.Api.methods)
- return methods_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >*
Api::mutable_methods() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.methods)
return &methods_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >&
+Api::methods() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Api.methods)
+ return methods_;
+}
// repeated .google.protobuf.Option options = 3;
int Api::options_size() const {
@@ -638,28 +753,28 @@ int Api::options_size() const {
void Api::clear_options() {
options_.Clear();
}
- const ::google::protobuf::Option& Api::options(int index) const {
+const ::google::protobuf::Option& Api::options(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.Api.options)
return options_.Get(index);
}
- ::google::protobuf::Option* Api::mutable_options(int index) {
+::google::protobuf::Option* Api::mutable_options(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.Api.options)
return options_.Mutable(index);
}
- ::google::protobuf::Option* Api::add_options() {
+::google::protobuf::Option* Api::add_options() {
// @@protoc_insertion_point(field_add:google.protobuf.Api.options)
return options_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
-Api::options() const {
- // @@protoc_insertion_point(field_list:google.protobuf.Api.options)
- return options_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
Api::mutable_options() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.options)
return &options_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Api::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Api.options)
+ return options_;
+}
// optional string version = 4;
void Api::clear_version() {
@@ -712,11 +827,11 @@ void Api::clear_source_context() {
if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
}
- const ::google::protobuf::SourceContext& Api::source_context() const {
+const ::google::protobuf::SourceContext& Api::source_context() const {
// @@protoc_insertion_point(field_get:google.protobuf.Api.source_context)
return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
}
- ::google::protobuf::SourceContext* Api::mutable_source_context() {
+::google::protobuf::SourceContext* Api::mutable_source_context() {
if (source_context_ == NULL) {
source_context_ = new ::google::protobuf::SourceContext;
@@ -724,13 +839,13 @@ void Api::clear_source_context() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Api.source_context)
return source_context_;
}
- ::google::protobuf::SourceContext* Api::release_source_context() {
+::google::protobuf::SourceContext* Api::release_source_context() {
::google::protobuf::SourceContext* temp = source_context_;
source_context_ = NULL;
return temp;
}
- void Api::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
+void Api::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
delete source_context_;
source_context_ = source_context;
if (source_context) {
@@ -741,6 +856,50 @@ void Api::clear_source_context() {
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.source_context)
}
+// repeated .google.protobuf.Mixin mixins = 6;
+int Api::mixins_size() const {
+ return mixins_.size();
+}
+void Api::clear_mixins() {
+ mixins_.Clear();
+}
+const ::google::protobuf::Mixin& Api::mixins(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Api.mixins)
+ return mixins_.Get(index);
+}
+::google::protobuf::Mixin* Api::mutable_mixins(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Api.mixins)
+ return mixins_.Mutable(index);
+}
+::google::protobuf::Mixin* Api::add_mixins() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Api.mixins)
+ return mixins_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >*
+Api::mutable_mixins() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.mixins)
+ return &mixins_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >&
+Api::mixins() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Api.mixins)
+ return mixins_;
+}
+
+// optional .google.protobuf.Syntax syntax = 7;
+void Api::clear_syntax() {
+ syntax_ = 0;
+}
+ ::google::protobuf::Syntax Api::syntax() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Api.syntax)
+ return static_cast< ::google::protobuf::Syntax >(syntax_);
+}
+ void Api::set_syntax(::google::protobuf::Syntax value) {
+
+ syntax_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Api.syntax)
+}
+
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -752,6 +911,7 @@ const int Method::kRequestStreamingFieldNumber;
const int Method::kResponseTypeUrlFieldNumber;
const int Method::kResponseStreamingFieldNumber;
const int Method::kOptionsFieldNumber;
+const int Method::kSyntaxFieldNumber;
#endif // !_MSC_VER
Method::Method()
@@ -781,6 +941,7 @@ void Method::SharedCtor() {
request_streaming_ = false;
response_type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
response_streaming_ = false;
+ syntax_ = 0;
}
Method::~Method() {
@@ -830,7 +991,7 @@ void Method::Clear() {
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
- ZR_(request_streaming_, response_streaming_);
+ ZR_(request_streaming_, syntax_);
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
request_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
response_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@@ -856,10 +1017,10 @@ bool Method::MergePartialFromCodedStream(
if (tag == 10) {
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_name()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.Method.name");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Method.name"));
} else {
goto handle_unusual;
}
@@ -873,10 +1034,10 @@ bool Method::MergePartialFromCodedStream(
parse_request_type_url:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_request_type_url()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->request_type_url().data(), this->request_type_url().length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.Method.request_type_url");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Method.request_type_url"));
} else {
goto handle_unusual;
}
@@ -905,10 +1066,10 @@ bool Method::MergePartialFromCodedStream(
parse_response_type_url:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_response_type_url()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->response_type_url().data(), this->response_type_url().length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.Method.response_type_url");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Method.response_type_url"));
} else {
goto handle_unusual;
}
@@ -944,6 +1105,22 @@ bool Method::MergePartialFromCodedStream(
}
if (input->ExpectTag(50)) goto parse_loop_options;
input->UnsafeDecrementRecursionDepth();
+ if (input->ExpectTag(56)) goto parse_syntax;
+ break;
+ }
+
+ // optional .google.protobuf.Syntax syntax = 7;
+ case 7: {
+ if (tag == 56) {
+ parse_syntax:
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ set_syntax(static_cast< ::google::protobuf::Syntax >(value));
+ } else {
+ goto handle_unusual;
+ }
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -974,9 +1151,9 @@ void Method::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_start:google.protobuf.Method)
// optional string name = 1;
if (this->name().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Method.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
@@ -984,9 +1161,9 @@ void Method::SerializeWithCachedSizes(
// optional string request_type_url = 2;
if (this->request_type_url().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->request_type_url().data(), this->request_type_url().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Method.request_type_url");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
2, this->request_type_url(), output);
@@ -999,9 +1176,9 @@ void Method::SerializeWithCachedSizes(
// optional string response_type_url = 4;
if (this->response_type_url().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->response_type_url().data(), this->response_type_url().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Method.response_type_url");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
4, this->response_type_url(), output);
@@ -1018,6 +1195,12 @@ void Method::SerializeWithCachedSizes(
6, this->options(i), output);
}
+ // optional .google.protobuf.Syntax syntax = 7;
+ if (this->syntax() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteEnum(
+ 7, this->syntax(), output);
+ }
+
// @@protoc_insertion_point(serialize_end:google.protobuf.Method)
}
@@ -1026,9 +1209,9 @@ void Method::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Method)
// optional string name = 1;
if (this->name().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Method.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
@@ -1037,9 +1220,9 @@ void Method::SerializeWithCachedSizes(
// optional string request_type_url = 2;
if (this->request_type_url().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->request_type_url().data(), this->request_type_url().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Method.request_type_url");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
@@ -1053,9 +1236,9 @@ void Method::SerializeWithCachedSizes(
// optional string response_type_url = 4;
if (this->response_type_url().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->response_type_url().data(), this->response_type_url().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Method.response_type_url");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
@@ -1074,6 +1257,12 @@ void Method::SerializeWithCachedSizes(
6, this->options(i), target);
}
+ // optional .google.protobuf.Syntax syntax = 7;
+ if (this->syntax() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+ 7, this->syntax(), target);
+ }
+
// @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Method)
return target;
}
@@ -1112,6 +1301,12 @@ int Method::ByteSize() const {
total_size += 1 + 1;
}
+ // optional .google.protobuf.Syntax syntax = 7;
+ if (this->syntax() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::EnumSize(this->syntax());
+ }
+
// repeated .google.protobuf.Option options = 6;
total_size += 1 * this->options_size();
for (int i = 0; i < this->options_size(); i++) {
@@ -1159,6 +1354,9 @@ void Method::MergeFrom(const Method& from) {
if (from.response_streaming() != 0) {
set_response_streaming(from.response_streaming());
}
+ if (from.syntax() != 0) {
+ set_syntax(from.syntax());
+ }
}
void Method::CopyFrom(const ::google::protobuf::Message& from) {
@@ -1189,6 +1387,7 @@ void Method::InternalSwap(Method* other) {
response_type_url_.Swap(&other->response_type_url_);
std::swap(response_streaming_, other->response_streaming_);
options_.UnsafeArenaSwap(&other->options_);
+ std::swap(syntax_, other->syntax_);
_internal_metadata_.Swap(&other->_internal_metadata_);
std::swap(_cached_size_, other->_cached_size_);
}
@@ -1368,27 +1567,409 @@ int Method::options_size() const {
void Method::clear_options() {
options_.Clear();
}
- const ::google::protobuf::Option& Method::options(int index) const {
+const ::google::protobuf::Option& Method::options(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.Method.options)
return options_.Get(index);
}
- ::google::protobuf::Option* Method::mutable_options(int index) {
+::google::protobuf::Option* Method::mutable_options(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.Method.options)
return options_.Mutable(index);
}
- ::google::protobuf::Option* Method::add_options() {
+::google::protobuf::Option* Method::add_options() {
// @@protoc_insertion_point(field_add:google.protobuf.Method.options)
return options_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Method::mutable_options() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Method.options)
+ return &options_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
Method::options() const {
// @@protoc_insertion_point(field_list:google.protobuf.Method.options)
return options_;
}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
-Method::mutable_options() {
- // @@protoc_insertion_point(field_mutable_list:google.protobuf.Method.options)
- return &options_;
+
+// optional .google.protobuf.Syntax syntax = 7;
+void Method::clear_syntax() {
+ syntax_ = 0;
+}
+ ::google::protobuf::Syntax Method::syntax() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Method.syntax)
+ return static_cast< ::google::protobuf::Syntax >(syntax_);
+}
+ void Method::set_syntax(::google::protobuf::Syntax value) {
+
+ syntax_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Method.syntax)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int Mixin::kNameFieldNumber;
+const int Mixin::kRootFieldNumber;
+#endif // !_MSC_VER
+
+Mixin::Mixin()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.Mixin)
+}
+
+void Mixin::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+Mixin::Mixin(const Mixin& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.Mixin)
+}
+
+void Mixin::SharedCtor() {
+ _is_default_instance_ = false;
+ ::google::protobuf::internal::GetEmptyString();
+ _cached_size_ = 0;
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ root_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+Mixin::~Mixin() {
+ // @@protoc_insertion_point(destructor:google.protobuf.Mixin)
+ SharedDtor();
+}
+
+void Mixin::SharedDtor() {
+ name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ root_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (this != default_instance_) {
+ }
+}
+
+void Mixin::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Mixin::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Mixin_descriptor_;
+}
+
+const Mixin& Mixin::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+ return *default_instance_;
+}
+
+Mixin* Mixin::default_instance_ = NULL;
+
+Mixin* Mixin::New(::google::protobuf::Arena* arena) const {
+ Mixin* n = new Mixin;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void Mixin::Clear() {
+ 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
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.Mixin)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional string name = 1;
+ case 1: {
+ if (tag == 10) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_name()));
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Mixin.name"));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(18)) goto parse_root;
+ break;
+ }
+
+ // optional string root = 2;
+ case 2: {
+ if (tag == 18) {
+ parse_root:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_root()));
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+ this->root().data(), this->root().length(),
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Mixin.root"));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.Mixin)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.Mixin)
+ return false;
+#undef DO_
+}
+
+void Mixin::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.Mixin)
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+ "google.protobuf.Mixin.name");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 1, this->name(), output);
+ }
+
+ // optional string root = 2;
+ if (this->root().size() > 0) {
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+ this->root().data(), this->root().length(),
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+ "google.protobuf.Mixin.root");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 2, this->root(), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.Mixin)
+}
+
+::google::protobuf::uint8* Mixin::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Mixin)
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+ "google.protobuf.Mixin.name");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 1, this->name(), target);
+ }
+
+ // optional string root = 2;
+ if (this->root().size() > 0) {
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+ this->root().data(), this->root().length(),
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+ "google.protobuf.Mixin.root");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 2, this->root(), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Mixin)
+ return target;
+}
+
+int Mixin::ByteSize() const {
+ int total_size = 0;
+
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->name());
+ }
+
+ // optional string root = 2;
+ if (this->root().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->root());
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void Mixin::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const Mixin* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Mixin>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void Mixin::MergeFrom(const Mixin& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from.name().size() > 0) {
+
+ name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+ }
+ if (from.root().size() > 0) {
+
+ root_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.root_);
+ }
+}
+
+void Mixin::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void Mixin::CopyFrom(const Mixin& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Mixin::IsInitialized() const {
+
+ return true;
+}
+
+void Mixin::Swap(Mixin* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void Mixin::InternalSwap(Mixin* other) {
+ name_.Swap(&other->name_);
+ root_.Swap(&other->root_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Mixin::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = Mixin_descriptor_;
+ metadata.reflection = Mixin_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Mixin
+
+// optional string name = 1;
+void Mixin::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Mixin::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Mixin.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Mixin::set_name(const ::std::string& value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Mixin.name)
+}
+ void Mixin::set_name(const char* value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.name)
+}
+ void Mixin::set_name(const char* value, size_t size) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.name)
+}
+ ::std::string* Mixin::mutable_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Mixin::release_name() {
+
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Mixin::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+
+ } else {
+
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.name)
+}
+
+// optional string root = 2;
+void Mixin::clear_root() {
+ root_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Mixin::root() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Mixin.root)
+ return root_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Mixin::set_root(const ::std::string& value) {
+
+ root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Mixin.root)
+}
+ void Mixin::set_root(const char* value) {
+
+ root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.root)
+}
+ void Mixin::set_root(const char* value, size_t size) {
+
+ root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.root)
+}
+ ::std::string* Mixin::mutable_root() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.root)
+ return root_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Mixin::release_root() {
+
+ return root_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Mixin::set_allocated_root(::std::string* root) {
+ if (root != NULL) {
+
+ } else {
+
+ }
+ root_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), root);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.root)
}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h
index 985adc5d..3c5a6f31 100644
--- a/src/google/protobuf/api.pb.h
+++ b/src/google/protobuf/api.pb.h
@@ -41,6 +41,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto();
class Api;
class Method;
+class Mixin;
// ===================================================================
@@ -118,10 +119,10 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message {
const ::google::protobuf::Method& methods(int index) const;
::google::protobuf::Method* mutable_methods(int index);
::google::protobuf::Method* add_methods();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >&
- methods() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >*
mutable_methods();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >&
+ methods() const;
// repeated .google.protobuf.Option options = 3;
int options_size() const;
@@ -130,10 +131,10 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message {
const ::google::protobuf::Option& options(int index) const;
::google::protobuf::Option* mutable_options(int index);
::google::protobuf::Option* add_options();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
- options() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
mutable_options();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+ options() const;
// optional string version = 4;
void clear_version();
@@ -155,6 +156,24 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message {
::google::protobuf::SourceContext* release_source_context();
void set_allocated_source_context(::google::protobuf::SourceContext* source_context);
+ // repeated .google.protobuf.Mixin mixins = 6;
+ int mixins_size() const;
+ void clear_mixins();
+ static const int kMixinsFieldNumber = 6;
+ const ::google::protobuf::Mixin& mixins(int index) const;
+ ::google::protobuf::Mixin* mutable_mixins(int index);
+ ::google::protobuf::Mixin* add_mixins();
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >*
+ mutable_mixins();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >&
+ mixins() const;
+
+ // optional .google.protobuf.Syntax syntax = 7;
+ void clear_syntax();
+ static const int kSyntaxFieldNumber = 7;
+ ::google::protobuf::Syntax syntax() const;
+ void set_syntax(::google::protobuf::Syntax value);
+
// @@protoc_insertion_point(class_scope:google.protobuf.Api)
private:
@@ -165,6 +184,8 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message {
::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
::google::protobuf::internal::ArenaStringPtr version_;
::google::protobuf::SourceContext* source_context_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin > mixins_;
+ int syntax_;
mutable int _cached_size_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto();
@@ -283,10 +304,16 @@ class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message {
const ::google::protobuf::Option& options(int index) const;
::google::protobuf::Option* mutable_options(int index);
::google::protobuf::Option* add_options();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
- options() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
mutable_options();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+ options() const;
+
+ // optional .google.protobuf.Syntax syntax = 7;
+ void clear_syntax();
+ static const int kSyntaxFieldNumber = 7;
+ ::google::protobuf::Syntax syntax() const;
+ void set_syntax(::google::protobuf::Syntax value);
// @@protoc_insertion_point(class_scope:google.protobuf.Method)
private:
@@ -296,9 +323,10 @@ class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message {
::google::protobuf::internal::ArenaStringPtr name_;
::google::protobuf::internal::ArenaStringPtr request_type_url_;
::google::protobuf::internal::ArenaStringPtr response_type_url_;
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
bool request_streaming_;
bool response_streaming_;
+ int syntax_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
mutable int _cached_size_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto();
@@ -307,6 +335,101 @@ class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message {
void InitAsDefaultInstance();
static Method* default_instance_;
};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT Mixin : public ::google::protobuf::Message {
+ public:
+ Mixin();
+ virtual ~Mixin();
+
+ Mixin(const Mixin& from);
+
+ inline Mixin& operator=(const Mixin& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const Mixin& default_instance();
+
+ void Swap(Mixin* other);
+
+ // implements Message ----------------------------------------------
+
+ inline Mixin* New() const { return New(NULL); }
+
+ Mixin* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const Mixin& from);
+ void MergeFrom(const Mixin& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(Mixin* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional string name = 1;
+ void clear_name();
+ static const int kNameFieldNumber = 1;
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
+
+ // optional string root = 2;
+ void clear_root();
+ static const int kRootFieldNumber = 2;
+ const ::std::string& root() const;
+ void set_root(const ::std::string& value);
+ void set_root(const char* value);
+ void set_root(const char* value, size_t size);
+ ::std::string* mutable_root();
+ ::std::string* release_root();
+ void set_allocated_root(::std::string* root);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.Mixin)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::internal::ArenaStringPtr name_;
+ ::google::protobuf::internal::ArenaStringPtr root_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto();
+
+ void InitAsDefaultInstance();
+ static Mixin* default_instance_;
+};
// ===================================================================
@@ -377,16 +500,16 @@ inline ::google::protobuf::Method* Api::add_methods() {
// @@protoc_insertion_point(field_add:google.protobuf.Api.methods)
return methods_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >&
-Api::methods() const {
- // @@protoc_insertion_point(field_list:google.protobuf.Api.methods)
- return methods_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >*
Api::mutable_methods() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.methods)
return &methods_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >&
+Api::methods() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Api.methods)
+ return methods_;
+}
// repeated .google.protobuf.Option options = 3;
inline int Api::options_size() const {
@@ -407,16 +530,16 @@ inline ::google::protobuf::Option* Api::add_options() {
// @@protoc_insertion_point(field_add:google.protobuf.Api.options)
return options_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
-Api::options() const {
- // @@protoc_insertion_point(field_list:google.protobuf.Api.options)
- return options_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
Api::mutable_options() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.options)
return &options_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Api::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Api.options)
+ return options_;
+}
// optional string version = 4;
inline void Api::clear_version() {
@@ -498,6 +621,50 @@ inline void Api::set_allocated_source_context(::google::protobuf::SourceContext*
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.source_context)
}
+// repeated .google.protobuf.Mixin mixins = 6;
+inline int Api::mixins_size() const {
+ return mixins_.size();
+}
+inline void Api::clear_mixins() {
+ mixins_.Clear();
+}
+inline const ::google::protobuf::Mixin& Api::mixins(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Api.mixins)
+ return mixins_.Get(index);
+}
+inline ::google::protobuf::Mixin* Api::mutable_mixins(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Api.mixins)
+ return mixins_.Mutable(index);
+}
+inline ::google::protobuf::Mixin* Api::add_mixins() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Api.mixins)
+ return mixins_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >*
+Api::mutable_mixins() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.mixins)
+ return &mixins_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >&
+Api::mixins() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Api.mixins)
+ return mixins_;
+}
+
+// optional .google.protobuf.Syntax syntax = 7;
+inline void Api::clear_syntax() {
+ syntax_ = 0;
+}
+inline ::google::protobuf::Syntax Api::syntax() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Api.syntax)
+ return static_cast< ::google::protobuf::Syntax >(syntax_);
+}
+inline void Api::set_syntax(::google::protobuf::Syntax value) {
+
+ syntax_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Api.syntax)
+}
+
// -------------------------------------------------------------------
// Method
@@ -678,20 +845,126 @@ inline ::google::protobuf::Option* Method::add_options() {
// @@protoc_insertion_point(field_add:google.protobuf.Method.options)
return options_.Add();
}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Method::mutable_options() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Method.options)
+ return &options_;
+}
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
Method::options() const {
// @@protoc_insertion_point(field_list:google.protobuf.Method.options)
return options_;
}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
-Method::mutable_options() {
- // @@protoc_insertion_point(field_mutable_list:google.protobuf.Method.options)
- return &options_;
+
+// optional .google.protobuf.Syntax syntax = 7;
+inline void Method::clear_syntax() {
+ syntax_ = 0;
+}
+inline ::google::protobuf::Syntax Method::syntax() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Method.syntax)
+ return static_cast< ::google::protobuf::Syntax >(syntax_);
+}
+inline void Method::set_syntax(::google::protobuf::Syntax value) {
+
+ syntax_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Method.syntax)
+}
+
+// -------------------------------------------------------------------
+
+// Mixin
+
+// optional string name = 1;
+inline void Mixin::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Mixin::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Mixin.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Mixin::set_name(const ::std::string& value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Mixin.name)
+}
+inline void Mixin::set_name(const char* value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.name)
+}
+inline void Mixin::set_name(const char* value, size_t size) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.name)
+}
+inline ::std::string* Mixin::mutable_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Mixin::release_name() {
+
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Mixin::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+
+ } else {
+
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.name)
+}
+
+// optional string root = 2;
+inline void Mixin::clear_root() {
+ root_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Mixin::root() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Mixin.root)
+ return root_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Mixin::set_root(const ::std::string& value) {
+
+ root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Mixin.root)
+}
+inline void Mixin::set_root(const char* value) {
+
+ root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.root)
+}
+inline void Mixin::set_root(const char* value, size_t size) {
+
+ root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.root)
+}
+inline ::std::string* Mixin::mutable_root() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.root)
+ return root_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Mixin::release_root() {
+
+ return root_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Mixin::set_allocated_root(::std::string* root) {
+ if (root != NULL) {
+
+ } else {
+
+ }
+ root_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), root);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.root)
}
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
// -------------------------------------------------------------------
+// -------------------------------------------------------------------
+
// @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/api.proto b/src/google/protobuf/api.proto
index d6c2a8b3..597a6497 100644
--- a/src/google/protobuf/api.proto
+++ b/src/google/protobuf/api.proto
@@ -34,15 +34,16 @@ package google.protobuf;
import "google/protobuf/source_context.proto";
import "google/protobuf/type.proto";
-option java_multiple_files = true;
-option java_outer_classname = "ApiProto";
option java_package = "com.google.protobuf";
+option java_outer_classname = "ApiProto";
+option java_multiple_files = true;
+option java_generate_equals_and_hash = true;
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
option objc_class_prefix = "GPB";
-
// Api is a light-weight descriptor for a protocol buffer service.
message Api {
+
// The fully qualified name of this api, including package name
// followed by the api's simple name.
string name = 1;
@@ -74,18 +75,22 @@ message Api {
// be omitted. Zero major versions must only be used for
// experimental, none-GA apis.
//
- // See also: [design doc](http://go/api-versioning).
- //
- //
string version = 4;
// Source context for the protocol buffer service represented by this
// message.
SourceContext source_context = 5;
+
+ // Included APIs. See [Mixin][].
+ repeated Mixin mixins = 6;
+
+ // The source syntax of the service.
+ Syntax syntax = 7;
}
// Method represents a method of an api.
message Method {
+
// The simple name of this method.
string name = 1;
@@ -103,4 +108,94 @@ message Method {
// Any metadata attached to the method.
repeated Option options = 6;
+
+ // The source syntax of this method.
+ Syntax syntax = 7;
+}
+
+// Declares an API to be included in this API. The including API must
+// redeclare all the methods from the included API, but documentation
+// and options are inherited as follows:
+//
+// - If after comment and whitespace stripping, the documentation
+// string of the redeclared method is empty, it will be inherited
+// from the original method.
+//
+// - Each annotation belonging to the service config (http,
+// visibility) which is not set in the redeclared method will be
+// inherited.
+//
+// - If an http annotation is inherited, the path pattern will be
+// modified as follows. Any version prefix will be replaced by the
+// version of the including API plus the [root][] path if specified.
+//
+// Example of a simple mixin:
+//
+// package google.acl.v1;
+// service AccessControl {
+// // Get the underlying ACL object.
+// rpc GetAcl(GetAclRequest) returns (Acl) {
+// option (google.api.http).get = "/v1/{resource=**}:getAcl";
+// }
+// }
+//
+// package google.storage.v2;
+// service Storage {
+// // (-- see AccessControl.GetAcl --)
+// rpc GetAcl(GetAclRequest) returns (Acl);
+//
+// // Get a data record.
+// rpc GetData(GetDataRequest) returns (Data) {
+// option (google.api.http).get = "/v2/{resource=**}";
+// }
+// }
+//
+// Example of a mixin configuration:
+//
+// apis:
+// - name: google.storage.v2.Storage
+// mixins:
+// - name: google.acl.v1.AccessControl
+//
+// The mixin construct implies that all methods in `AccessControl` are
+// also declared with same name and request/response types in
+// `Storage`. A documentation generator or annotation processor will
+// see the effective `Storage.GetAcl` method after inherting
+// documentation and annotations as follows:
+//
+// service Storage {
+// // Get the underlying ACL object.
+// rpc GetAcl(GetAclRequest) returns (Acl) {
+// option (google.api.http).get = "/v2/{resource=**}:getAcl";
+// }
+// ...
+// }
+//
+// Note how the version in the path pattern changed from `v1` to `v2`.
+//
+// If the `root` field in the mixin is specified, it should be a
+// relative path under which inherited HTTP paths are placed. Example:
+//
+// apis:
+// - name: google.storage.v2.Storage
+// mixins:
+// - name: google.acl.v1.AccessControl
+// root: acls
+//
+// This implies the following inherited HTTP annotation:
+//
+// service Storage {
+// // Get the underlying ACL object.
+// rpc GetAcl(GetAclRequest) returns (Acl) {
+// option (google.api.http).get = "/v2/acls/{resource=**}:getAcl";
+// }
+// ...
+// }
+message Mixin {
+ // The fully qualified name of the API which is included.
+ string name = 1;
+
+ // If non-empty specifies a path under which inherited HTTP paths
+ // are rooted.
+ string root = 2;
}
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index f499108d..2d66dfd7 100755
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -69,8 +69,12 @@ void Arena::Init() {
first_block->size = options_.initial_block_size;
first_block->pos = kHeaderSize;
first_block->next = NULL;
- first_block->owner = &first_block->owner;
- AddBlock(first_block);
+ // Thread which calls Init() owns the first block. This allows the
+ // single-threaded case to allocate on the first block without taking any
+ // locks.
+ first_block->owner = &thread_cache();
+ SetThreadCacheBlock(first_block);
+ AddBlockInternal(first_block);
owns_first_block_ = false;
}
@@ -83,7 +87,7 @@ void Arena::Init() {
}
Arena::~Arena() {
- uint64 space_allocated = Reset();
+ uint64 space_allocated = ResetInternal();
// Call the destruction hook
if (options_.on_arena_destruction != NULL) {
@@ -92,10 +96,14 @@ Arena::~Arena() {
}
uint64 Arena::Reset() {
- CleanupList();
- uint64 space_allocated = FreeBlocks();
// Invalidate any ThreadCaches pointing to any blocks we just destroyed.
lifecycle_id_ = lifecycle_id_generator_.GetNext();
+ return ResetInternal();
+}
+
+uint64 Arena::ResetInternal() {
+ CleanupList();
+ uint64 space_allocated = FreeBlocks();
// Call the reset hook
if (options_.on_arena_reset != NULL) {
@@ -140,6 +148,10 @@ Arena::Block* Arena::NewBlock(void* me, Block* my_last_block, size_t n,
void Arena::AddBlock(Block* b) {
MutexLock l(&blocks_lock_);
+ AddBlockInternal(b);
+}
+
+void Arena::AddBlockInternal(Block* b) {
b->next = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
google::protobuf::internal::Release_Store(&blocks_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
if (b->avail() != 0) {
@@ -184,16 +196,6 @@ void* Arena::AllocateAligned(const std::type_info* allocated, size_t n) {
void* me = &thread_cache();
Block* b = reinterpret_cast<Block*>(google::protobuf::internal::Acquire_Load(&hint_));
if (!b || b->owner != me || b->avail() < n) {
- // If the next block to allocate from is the first block, try to claim it
- // for this thread.
- if (!owns_first_block_ && b->next == NULL) {
- MutexLock l(&blocks_lock_);
- if (b->owner == &b->owner && b->avail() >= n) {
- b->owner = me;
- SetThreadCacheBlock(b);
- return AllocFromBlock(b, n);
- }
- }
return SlowAlloc(n);
}
return AllocFromBlock(b, n);
@@ -270,8 +272,12 @@ uint64 Arena::FreeBlocks() {
// Make the first block that was passed in through ArenaOptions
// available for reuse.
first_block->pos = kHeaderSize;
- first_block->owner = &first_block->owner;
- AddBlock(first_block);
+ // Thread which calls Reset() owns the first block. This allows the
+ // single-threaded case to allocate on the first block without taking any
+ // locks.
+ first_block->owner = &thread_cache();
+ SetThreadCacheBlock(first_block);
+ AddBlockInternal(first_block);
}
return space_allocated;
}
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index e7e693b2..074a9e54 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -31,6 +31,10 @@
#ifndef GOOGLE_PROTOBUF_ARENA_H__
#define GOOGLE_PROTOBUF_ARENA_H__
+#include <limits>
+#ifdef max
+#undef max // Visual Studio defines this macro
+#endif
#if __cplusplus >= 201103L
#include <google/protobuf/stubs/type_traits.h>
#endif
@@ -39,7 +43,8 @@
#include <google/protobuf/stubs/atomic_sequence_num.h>
#include <google/protobuf/stubs/atomicops.h>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/platform_macros.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/mutex.h>
#include <google/protobuf/stubs/type_traits.h>
namespace google {
@@ -414,6 +419,9 @@ class LIBPROTOBUF_EXPORT Arena {
// trivially destructible.
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
static T* CreateArray(::google::protobuf::Arena* arena, size_t num_elements) {
+ GOOGLE_CHECK_LE(num_elements,
+ std::numeric_limits<size_t>::max() / sizeof(T))
+ << "Requested size is too large to fit into size_t.";
if (arena == NULL) {
return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
} else {
@@ -459,7 +467,8 @@ class LIBPROTOBUF_EXPORT Arena {
// will be manually called when the arena is destroyed or reset. This differs
// from OwnDestructor() in that any member function may be specified, not only
// the class destructor.
- GOOGLE_ATTRIBUTE_NOINLINE void OwnCustomDestructor(void* object, void (*destruct)(void*)) {
+ GOOGLE_ATTRIBUTE_NOINLINE void OwnCustomDestructor(void* object,
+ void (*destruct)(void*)) {
AddListNode(object, destruct);
}
@@ -468,7 +477,7 @@ class LIBPROTOBUF_EXPORT Arena {
// latter is a virtual call, while this method is a templated call that
// resolves at compile-time.
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- static inline ::google::protobuf::Arena* GetArena(const T* value) {
+ static ::google::protobuf::Arena* GetArena(const T* value) {
return GetArenaInternal(value, static_cast<T*>(0));
}
@@ -506,7 +515,7 @@ class LIBPROTOBUF_EXPORT Arena {
// aligned at a multiple of 8 bytes.
size_t pos;
size_t size; // total size of the block.
- size_t avail() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE { return size - pos; }
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE size_t avail() const { return size - pos; }
// data follows
};
@@ -554,6 +563,33 @@ class LIBPROTOBUF_EXPORT Arena {
return google::protobuf::internal::has_trivial_destructor<T>::value;
}
+ // Helper typetrait that indicates whether the desctructor of type T should be
+ // called when arena is destroyed at compile time. This is only to allow
+ // construction of higher-level templated utilities.
+ // is_destructor_skippable<T>::value is an instance of google::protobuf::internal::true_type if the
+ // destructor of the message type T should not be called when arena is
+ // destroyed or google::protobuf::internal::has_trivial_destructor<T>::value == true, and
+ // google::protobuf::internal::false_type otherwise.
+ //
+ // This is inside Arena because only Arena has the friend relationships
+ // necessary to see the underlying generated code traits.
+ template<typename T>
+ struct is_destructor_skippable {
+ template<typename U>
+ static char DestructorSkippable(
+ const typename U::DestructorSkippable_*);
+ template<typename U>
+ static double DestructorSkippable(...);
+
+ // This will resolve to either google::protobuf::internal::true_type or google::protobuf::internal::false_type.
+ typedef google::protobuf::internal::integral_constant<bool,
+ sizeof(DestructorSkippable<const T>(static_cast<const T*>(0))) ==
+ sizeof(char) || google::protobuf::internal::has_trivial_destructor<T>::value == true>
+ type;
+ static const type value;
+ };
+
+
// CreateMessage<T> requires that T supports arenas, but this private method
// works whether or not T supports arenas. These are not exposed to user code
// as it can cause confusing API usages, and end up having double free in
@@ -573,14 +609,16 @@ class LIBPROTOBUF_EXPORT Arena {
// Just allocate the required size for the given type assuming the
// type has a trivial constructor.
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- inline T* CreateInternalRawArray(size_t num_elements) {
+ T* CreateInternalRawArray(size_t num_elements) {
+ GOOGLE_CHECK_LE(num_elements,
+ std::numeric_limits<size_t>::max() / sizeof(T))
+ << "Requested size is too large to fit into size_t.";
return static_cast<T*>(
AllocateAligned(RTTI_TYPE_ID(T), sizeof(T) * num_elements));
}
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- inline T* CreateInternal(
- bool skip_explicit_ownership) {
+ T* CreateInternal(bool skip_explicit_ownership) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T();
if (!skip_explicit_ownership) {
AddListNode(t, &internal::arena_destruct_object<T>);
@@ -589,8 +627,7 @@ class LIBPROTOBUF_EXPORT Arena {
}
template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- inline T* CreateInternal(
- bool skip_explicit_ownership, const Arg& arg) {
+ T* CreateInternal(bool skip_explicit_ownership, const Arg& arg) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg);
if (!skip_explicit_ownership) {
AddListNode(t, &internal::arena_destruct_object<T>);
@@ -599,7 +636,7 @@ class LIBPROTOBUF_EXPORT Arena {
}
template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- inline T* CreateInternal(
+ T* CreateInternal(
bool skip_explicit_ownership, const Arg1& arg1, const Arg2& arg2) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2);
if (!skip_explicit_ownership) {
@@ -609,10 +646,10 @@ class LIBPROTOBUF_EXPORT Arena {
}
template <typename T, typename Arg1, typename Arg2, typename Arg3>
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
- const Arg1& arg1,
- const Arg2& arg2,
- const Arg3& arg3) {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
T(arg1, arg2, arg3);
if (!skip_explicit_ownership) {
@@ -623,11 +660,11 @@ class LIBPROTOBUF_EXPORT Arena {
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4>
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
- const Arg1& arg1,
- const Arg2& arg2,
- const Arg3& arg3,
- const Arg4& arg4) {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
T(arg1, arg2, arg3, arg4);
if (!skip_explicit_ownership) {
@@ -638,12 +675,12 @@ class LIBPROTOBUF_EXPORT Arena {
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5>
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
- const Arg1& arg1,
- const Arg2& arg2,
- const Arg3& arg3,
- const Arg4& arg4,
- const Arg5& arg5) {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4,
+ const Arg5& arg5) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
T(arg1, arg2, arg3, arg4, arg5);
if (!skip_explicit_ownership) {
@@ -654,13 +691,13 @@ class LIBPROTOBUF_EXPORT Arena {
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5, typename Arg6>
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
- const Arg1& arg1,
- const Arg2& arg2,
- const Arg3& arg3,
- const Arg4& arg4,
- const Arg5& arg5,
- const Arg6& arg6) {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4,
+ const Arg5& arg5,
+ const Arg6& arg6) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
T(arg1, arg2, arg3, arg4, arg5, arg6);
if (!skip_explicit_ownership) {
@@ -671,14 +708,14 @@ class LIBPROTOBUF_EXPORT Arena {
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5, typename Arg6, typename Arg7>
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
- const Arg1& arg1,
- const Arg2& arg2,
- const Arg3& arg3,
- const Arg4& arg4,
- const Arg5& arg5,
- const Arg6& arg6,
- const Arg7& arg7) {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4,
+ const Arg5& arg5,
+ const Arg6& arg6,
+ const Arg7& arg7) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
if (!skip_explicit_ownership) {
@@ -690,15 +727,15 @@ class LIBPROTOBUF_EXPORT Arena {
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5, typename Arg6, typename Arg7,
typename Arg8>
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
- const Arg1& arg1,
- const Arg2& arg2,
- const Arg3& arg3,
- const Arg4& arg4,
- const Arg5& arg5,
- const Arg6& arg6,
- const Arg7& arg7,
- const Arg8& arg8) {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4,
+ const Arg5& arg5,
+ const Arg6& arg6,
+ const Arg7& arg7,
+ const Arg8& arg8) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
if (!skip_explicit_ownership) {
@@ -708,21 +745,21 @@ class LIBPROTOBUF_EXPORT Arena {
}
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*) {
+ T* CreateMessageInternal(typename T::InternalArenaConstructable_*) {
return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
this);
}
template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
- const Arg& arg) {
+ T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
+ const Arg& arg) {
return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
this, arg);
}
template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
- const Arg1& arg1, const Arg2& arg2) {
+ T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
+ const Arg1& arg1, const Arg2& arg2) {
return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
this, arg1, arg2);
}
@@ -733,19 +770,29 @@ class LIBPROTOBUF_EXPORT Arena {
template <typename T>
static void CreateInArenaStorage(T* ptr, Arena* arena) {
CreateInArenaStorageInternal(ptr, arena, is_arena_constructable<T>::value);
+ RegisterDestructorInternal(ptr, arena, is_destructor_skippable<T>::value);
}
+
template <typename T>
static void CreateInArenaStorageInternal(
T* ptr, Arena* arena, google::protobuf::internal::true_type) {
new (ptr) T(arena);
}
-
template <typename T>
static void CreateInArenaStorageInternal(
T* ptr, Arena* arena, google::protobuf::internal::false_type) {
new (ptr) T;
}
+ template <typename T>
+ static void RegisterDestructorInternal(
+ T* ptr, Arena* arena, google::protobuf::internal::true_type) {}
+ template <typename T>
+ static void RegisterDestructorInternal(
+ T* ptr, Arena* arena, google::protobuf::internal::false_type) {
+ arena->OwnDestructor(ptr);
+ }
+
// These implement Own(), which registers an object for deletion (destructor
// call and operator delete()). The second parameter has type 'true_type' if T
// is a subtype of ::google::protobuf::Message and 'false_type' otherwise. Collapsing
@@ -768,13 +815,13 @@ class LIBPROTOBUF_EXPORT Arena {
// InternalArenaConstructable_ tags can be associated with an arena, and such
// objects must implement a GetArenaNoVirtual() method.
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- static inline ::google::protobuf::Arena* GetArenaInternal(const T* value,
- typename T::InternalArenaConstructable_*) {
+ static ::google::protobuf::Arena* GetArenaInternal(
+ const T* value, typename T::InternalArenaConstructable_*) {
return value->GetArenaNoVirtual();
}
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- static inline ::google::protobuf::Arena* GetArenaInternal(const T* value, ...) {
+ static ::google::protobuf::Arena* GetArenaInternal(const T* value, ...) {
return NULL;
}
@@ -784,7 +831,7 @@ class LIBPROTOBUF_EXPORT Arena {
void* AllocateAligned(const std::type_info* allocated, size_t n);
// Allocate an internal allocation, avoiding optional typed monitoring.
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline void* AllocateAligned(size_t n) {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* AllocateAligned(size_t n) {
return AllocateAligned(NULL, n);
}
@@ -802,6 +849,7 @@ class LIBPROTOBUF_EXPORT Arena {
void AddListNode(void* elem, void (*cleanup)(void*));
// Delete or Destruct all objects owned by the arena.
void CleanupList();
+ uint64 ResetInternal();
inline void SetThreadCacheBlock(Block* block) {
thread_cache().last_block_used_ = block;
@@ -828,6 +876,9 @@ class LIBPROTOBUF_EXPORT Arena {
Mutex blocks_lock_;
void AddBlock(Block* b);
+ // Access must be synchronized, either by blocks_lock_ or by being called from
+ // Init()/Reset().
+ void AddBlockInternal(Block* b);
void* SlowAlloc(size_t n);
Block* FindBlock(void* me);
Block* NewBlock(void* me, Block* my_last_block, size_t n,
@@ -853,6 +904,11 @@ const typename Arena::is_arena_constructable<T>::type
Arena::is_arena_constructable<T>::value =
typename Arena::is_arena_constructable<T>::type();
+template<typename T>
+const typename Arena::is_destructor_skippable<T>::type
+ Arena::is_destructor_skippable<T>::value =
+ typename Arena::is_destructor_skippable<T>::type();
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/arena_test_util.cc b/src/google/protobuf/arena_test_util.cc
index 21f55c6e..df9c5bd6 100644
--- a/src/google/protobuf/arena_test_util.cc
+++ b/src/google/protobuf/arena_test_util.cc
@@ -28,6 +28,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/arena_test_util.h>
diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc
index 6c185695..c9ca1fd1 100644
--- a/src/google/protobuf/arena_unittest.cc
+++ b/src/google/protobuf/arena_unittest.cc
@@ -40,7 +40,9 @@
#include <typeinfo>
#include <vector>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/arena_test_util.h>
#include <google/protobuf/test_util.h>
#include <google/protobuf/unittest.pb.h>
@@ -619,8 +621,6 @@ TEST(ArenaTest, RepeatedPtrFieldAddClearedTest) {
}
}
-// N.B.: no reflection version of this test because all the arena-specific code
-// is in RepeatedPtrField, and the reflection works implicitly based on that.
TEST(ArenaTest, AddAllocatedToRepeatedField) {
// Heap->arena case.
Arena arena1;
@@ -680,6 +680,55 @@ TEST(ArenaTest, AddAllocatedToRepeatedField) {
}
}
+TEST(ArenaTest, AddAllocatedToRepeatedFieldViaReflection) {
+ // Heap->arena case.
+ Arena arena1;
+ TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+ const Reflection* r = arena1_message->GetReflection();
+ const Descriptor* d = arena1_message->GetDescriptor();
+ const FieldDescriptor* fd =
+ d->FindFieldByName("repeated_nested_message");
+ for (int i = 0; i < 10; i++) {
+ TestAllTypes::NestedMessage* heap_submessage =
+ new TestAllTypes::NestedMessage;
+ heap_submessage->set_bb(42);
+ r->AddAllocatedMessage(arena1_message, fd, heap_submessage);
+ // Should not copy object -- will use arena_->Own().
+ EXPECT_EQ(heap_submessage,
+ &arena1_message->repeated_nested_message(i));
+ EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
+ }
+
+ // Arena1->Arena2 case.
+ arena1_message->Clear();
+ for (int i = 0; i < 10; i++) {
+ Arena arena2;
+ TestAllTypes::NestedMessage* arena2_submessage =
+ Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+ arena2_submessage->set_bb(42);
+ r->AddAllocatedMessage(arena1_message, fd, arena2_submessage);
+ // Should copy object.
+ EXPECT_NE(arena2_submessage,
+ &arena1_message->repeated_nested_message(i));
+ EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
+ }
+
+ // Arena->heap case.
+ TestAllTypes* heap_message = new TestAllTypes;
+ for (int i = 0; i < 10; i++) {
+ Arena arena2;
+ TestAllTypes::NestedMessage* arena2_submessage =
+ Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+ arena2_submessage->set_bb(42);
+ r->AddAllocatedMessage(heap_message, fd, arena2_submessage);
+ // Should copy object.
+ EXPECT_NE(arena2_submessage,
+ &heap_message->repeated_nested_message(i));
+ EXPECT_EQ(42, heap_message->repeated_nested_message(i).bb());
+ }
+ delete heap_message;
+}
+
TEST(ArenaTest, ReleaseLastRepeatedField) {
// Release from arena-allocated repeated field and ensure that returned object
// is heap-allocated.
@@ -1230,7 +1279,7 @@ TEST(ArenaTest, ArenaHooksSanity) {
EXPECT_EQ(1, ArenaHooksTestUtil::num_init);
EXPECT_EQ(0, ArenaHooksTestUtil::num_allocations);
::google::protobuf::Arena::Create<uint64>(&arena);
- if (::google::protobuf::internal::has_trivial_destructor<uint64>::value) {
+ if (google::protobuf::internal::has_trivial_destructor<uint64>::value) {
EXPECT_EQ(1, ArenaHooksTestUtil::num_allocations);
} else {
EXPECT_EQ(2, ArenaHooksTestUtil::num_allocations);
diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h
index 7bbf6c76..1dacdc68 100755
--- a/src/google/protobuf/arenastring.h
+++ b/src/google/protobuf/arenastring.h
@@ -33,6 +33,7 @@
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/fastmem.h>
@@ -145,7 +146,7 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
// Swaps internal pointers. Arena-safety semantics: this is guarded by the
// logic in Swap()/UnsafeArenaSwap() at the message level, so this method is
// 'unsafe' if called directly.
- inline void Swap(ArenaStringPtr* other) GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(ArenaStringPtr* other) {
std::swap(ptr_, other->ptr_);
}
@@ -283,9 +284,8 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
private:
::std::string* ptr_;
- GOOGLE_ATTRIBUTE_NOINLINE
- inline void CreateInstance(::google::protobuf::Arena* arena,
- const ::std::string* initial_value) {
+ GOOGLE_ATTRIBUTE_NOINLINE void CreateInstance(::google::protobuf::Arena* arena,
+ const ::std::string* initial_value) {
// Assumes ptr_ is not NULL.
if (initial_value != NULL) {
ptr_ = new ::std::string(*initial_value);
@@ -296,9 +296,7 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
arena->Own(ptr_);
}
}
-
- GOOGLE_ATTRIBUTE_NOINLINE
- inline void CreateInstanceNoArena(const ::std::string* initial_value) {
+ GOOGLE_ATTRIBUTE_NOINLINE void CreateInstanceNoArena(const ::std::string* initial_value) {
if (initial_value != NULL) {
ptr_ = new ::std::string(*initial_value);
} else {
diff --git a/src/google/protobuf/arenastring_unittest.cc b/src/google/protobuf/arenastring_unittest.cc
index 8ebd4b9c..3fb582be 100644
--- a/src/google/protobuf/arenastring_unittest.cc
+++ b/src/google/protobuf/arenastring_unittest.cc
@@ -42,6 +42,7 @@
#endif
#include <cstdlib>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc
index 0039b00a..473eb4e6 100644
--- a/src/google/protobuf/compiler/code_generator.cc
+++ b/src/google/protobuf/compiler/code_generator.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index e8871861..26a4f0b0 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -70,6 +70,7 @@
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/stubs/map_util.h>
@@ -1657,7 +1658,11 @@ bool CommandLineInterface::WriteDescriptorSet(
&already_seen, file_set.mutable_file());
}
} else {
+ set<const FileDescriptor*> already_seen;
for (int i = 0; i < parsed_files.size(); i++) {
+ if (!already_seen.insert(parsed_files[i]).second) {
+ continue;
+ }
FileDescriptorProto* file_proto = file_set.add_file();
parsed_files[i]->CopyTo(file_proto);
if (source_info_in_descriptor_set_) {
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index e5b77c33..9560d0e0 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -63,13 +63,13 @@
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
+namespace google {
+namespace protobuf {
+namespace compiler {
// Disable the whole test when we use tcmalloc for "draconian" heap checks, in
// which case tcmalloc will print warnings that fail the plugin tests.
#if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
-namespace google {
-namespace protobuf {
-namespace compiler {
#if defined(_WIN32)
#ifndef STDIN_FILENO
@@ -886,6 +886,39 @@ TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) {
EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
}
+TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithDuplicates) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "import \"foo.proto\";\n"
+ "message Bar {\n"
+ " optional Foo foo = 1;\n"
+ "}\n");
+ CreateTempFile("baz.proto",
+ "syntax = \"proto2\";\n"
+ "import \"foo.proto\";\n"
+ "message Baz {\n"
+ " optional Foo foo = 1;\n"
+ "}\n");
+
+ Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
+ "--proto_path=$tmpdir bar.proto foo.proto bar.proto baz.proto");
+
+ ExpectNoErrors();
+
+ FileDescriptorSet descriptor_set;
+ ReadDescriptorSet("descriptor_set", &descriptor_set);
+ if (HasFatalFailure()) return;
+ EXPECT_EQ(3, descriptor_set.file_size());
+ EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
+ EXPECT_EQ("foo.proto", descriptor_set.file(1).name());
+ EXPECT_EQ("baz.proto", descriptor_set.file(2).name());
+ // Descriptor set should not have source code info.
+ EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
+}
+
TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) {
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
@@ -1767,8 +1800,8 @@ TEST_F(EncodeDecodeTest, ProtoParseError) {
} // anonymous namespace
+#endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
+
} // namespace compiler
} // namespace protobuf
-
-#endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
} // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index 13ed0b64..c3e9fe74 100644
--- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -133,8 +133,7 @@ TEST(BootstrapTest, GeneratedDescriptorMatches) {
CppGenerator generator;
MockGeneratorContext context;
string error;
- string parameter;
- parameter = "dllexport_decl=LIBPROTOBUF_EXPORT";
+ string parameter = "dllexport_decl=LIBPROTOBUF_EXPORT";
ASSERT_TRUE(generator.Generate(proto_file, parameter,
&context, &error));
parameter = "dllexport_decl=LIBPROTOC_EXPORT";
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 70d3a600..de4d7cc7 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -32,7 +32,6 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <set>
#include <map>
#include <google/protobuf/compiler/cpp/cpp_enum.h>
@@ -70,14 +69,11 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
EnumGenerator::~EnumGenerator() {}
-void EnumGenerator::GenerateForwardDeclaration(io::Printer* printer) {
+void EnumGenerator::FillForwardDeclaration(set<string>* enum_names) {
if (!options_.proto_h) {
return;
}
- map<string, string> vars;
- vars["classname"] = classname_;
- printer->Print(vars, "enum $classname$ : int;\n");
- printer->Print(vars, "bool $classname$_IsValid(int value);\n");
+ enum_names->insert(classname_);
}
void EnumGenerator::GenerateDefinition(io::Printer* printer) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h
index 3e930856..f3aa72e4 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.h
@@ -35,6 +35,7 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
+#include <set>
#include <string>
#include <google/protobuf/compiler/cpp/cpp_options.h>
#include <google/protobuf/descriptor.h>
@@ -60,11 +61,11 @@ class EnumGenerator {
// Header stuff.
- // Generate header code to forward-declare the enum. This is for use when
+ // Fills the name to use when declaring the enum. This is for use when
// generating other .proto.h files. This code should be placed within the
// enum's package namespace, but NOT within any class, even for nested
// enums.
- void GenerateForwardDeclaration(io::Printer* printer);
+ void FillForwardDeclaration(set<string>* enum_names);
// Generate header code defining the enum. This code should be placed
// within the enum's package namespace, but NOT within any class, even for
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 965327b1..824e2205 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -35,7 +35,6 @@
#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc
index 43df1d88..8d47d4e0 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -47,6 +47,7 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index 1f0a8205..8e8bd8b7 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -33,6 +33,7 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/cpp/cpp_file.h>
+#include <map>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
@@ -93,22 +94,36 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
FileGenerator::~FileGenerator() {}
-void FileGenerator::GenerateHeader(io::Printer* printer) {
- GenerateTopHeaderGuard(printer);
+void FileGenerator::GenerateProtoHeader(io::Printer* printer) {
+ if (!options_.proto_h) {
+ return;
+ }
+
+ string filename_identifier = FilenameIdentifier(file_->name());
+ GenerateTopHeaderGuard(printer, filename_identifier);
+
GenerateLibraryIncludes(printer);
- GenerateDependencyIncludes(printer);
+
+ for (int i = 0; i < file_->public_dependency_count(); i++) {
+ const FileDescriptor* dep = file_->public_dependency(i);
+ const char* extension = ".proto.h";
+ string dependency = StripProto(dep->name()) + extension;
+ printer->Print(
+ "#include \"$dependency$\" // IWYU pragma: export\n",
+ "dependency", dependency);
+ }
printer->Print(
"// @@protoc_insertion_point(includes)\n");
+ GenerateForwardDeclarations(printer);
// Open namespace.
GenerateNamespaceOpeners(printer);
GenerateGlobalStateFunctionDeclarations(printer);
- GenerateMessageForwardDeclarations(printer);
printer->Print("\n");
@@ -133,6 +148,11 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
GenerateInlineFunctionDefinitions(printer);
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n"
+ "\n");
+
// Close up namespace.
GenerateNamespaceClosers(printer);
@@ -144,19 +164,89 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"// @@protoc_insertion_point(global_scope)\n"
"\n");
- GenerateBottomHeaderGuard(printer);
+ GenerateBottomHeaderGuard(printer, filename_identifier);
+}
+
+void FileGenerator::GeneratePBHeader(io::Printer* printer) {
+ string filename_identifier =
+ FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : ""));
+ GenerateTopHeaderGuard(printer, filename_identifier);
+
+ if (options_.proto_h) {
+ printer->Print("#include \"$basename$.proto.h\" // IWYU pragma: export\n",
+ "basename", StripProto(file_->name()));
+ } else {
+ GenerateLibraryIncludes(printer);
+ }
+ GenerateDependencyIncludes(printer);
+
+ printer->Print(
+ "// @@protoc_insertion_point(includes)\n");
+
+
+
+ // Open namespace.
+ GenerateNamespaceOpeners(printer);
+
+ if (!options_.proto_h) {
+ GenerateGlobalStateFunctionDeclarations(printer);
+ GenerateMessageForwardDeclarations(printer);
+
+ printer->Print("\n");
+
+ GenerateEnumDefinitions(printer);
+
+ printer->Print(kThickSeparator);
+ printer->Print("\n");
+
+ GenerateMessageDefinitions(printer);
+
+ printer->Print("\n");
+ printer->Print(kThickSeparator);
+ printer->Print("\n");
+
+ GenerateServiceDefinitions(printer);
+
+ GenerateExtensionIdentifiers(printer);
+
+ printer->Print("\n");
+ printer->Print(kThickSeparator);
+ printer->Print("\n");
+
+ GenerateInlineFunctionDefinitions(printer);
+ }
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n");
+
+ // Close up namespace.
+ GenerateNamespaceClosers(printer);
+
+ if (!options_.proto_h) {
+ // We need to specialize some templates in the ::google::protobuf namespace:
+ GenerateProto2NamespaceEnumSpecializations(printer);
+ }
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(global_scope)\n"
+ "\n");
+
+ GenerateBottomHeaderGuard(printer, filename_identifier);
}
void FileGenerator::GenerateSource(io::Printer* printer) {
+ string header =
+ StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h");
printer->Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
"// source: $filename$\n"
"\n"
-
// The generated code calls accessors that might be deprecated. We don't
// want the compiler to warn in generated code.
"#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
- "#include \"$basename$.pb.h\"\n"
+ "#include \"$header$\"\n"
"\n"
"#include <algorithm>\n" // for swap()
"\n"
@@ -165,7 +255,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"#include <google/protobuf/io/coded_stream.h>\n"
"#include <google/protobuf/wire_format_lite_inl.h>\n",
"filename", file_->name(),
- "basename", StripProto(file_->name()));
+ "header", header);
// Unknown fields implementation in lite mode uses StringOutputStream
if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
@@ -181,6 +271,18 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"#include <google/protobuf/wire_format.h>\n");
}
+ if (options_.proto_h) {
+ // Use the smaller .proto.h files.
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ const FileDescriptor* dep = file_->dependency(i);
+ const char* extension = ".proto.h";
+ string dependency = StripProto(dep->name()) + extension;
+ printer->Print(
+ "#include \"$dependency$\"\n",
+ "dependency", dependency);
+ }
+ }
+
printer->Print(
"// @@protoc_insertion_point(includes)\n");
@@ -276,6 +378,59 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"// @@protoc_insertion_point(global_scope)\n");
}
+class FileGenerator::ForwardDeclarations {
+ public:
+ ~ForwardDeclarations() {
+ for (map<string, ForwardDeclarations *>::iterator it = namespaces_.begin(),
+ end = namespaces_.end();
+ it != end; ++it) {
+ delete it->second;
+ }
+ namespaces_.clear();
+ }
+
+ ForwardDeclarations* AddOrGetNamespace(const string& ns_name) {
+ ForwardDeclarations*& ns = namespaces_[ns_name];
+ if (ns == NULL) {
+ ns = new ForwardDeclarations;
+ }
+ return ns;
+ }
+
+ set<string>& classes() { return classes_; }
+ set<string>& enums() { return enums_; }
+
+ void Print(io::Printer* printer) const {
+ for (set<string>::const_iterator it = enums_.begin(), end = enums_.end();
+ it != end; ++it) {
+ printer->Print("enum $enumname$ : int;\n"
+ "bool $enumname$_IsValid(int value);\n",
+ "enumname", it->c_str());
+ }
+ for (set<string>::const_iterator it = classes_.begin(),
+ end = classes_.end();
+ it != end; ++it) {
+ printer->Print("class $classname$;\n", "classname", it->c_str());
+ }
+ for (map<string, ForwardDeclarations *>::const_iterator
+ it = namespaces_.begin(),
+ end = namespaces_.end();
+ it != end; ++it) {
+ printer->Print("namespace $nsname$ {\n",
+ "nsname", it->first);
+ it->second->Print(printer);
+ printer->Print("} // namespace $nsname$\n",
+ "nsname", it->first);
+ }
+ }
+
+
+ private:
+ map<string, ForwardDeclarations*> namespaces_;
+ set<string> classes_;
+ set<string> enums_;
+};
+
void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// AddDescriptors() is a file-level procedure which adds the encoded
// FileDescriptorProto for this .proto file to the global DescriptorPool for
@@ -434,12 +589,22 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
string file_data;
file_proto.SerializeToString(&file_data);
+#ifdef _MSC_VER
+ bool breakdown_large_file = true;
+#else
+ bool breakdown_large_file = false;
+#endif
// Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535
// bytes in length". Declare a static array of characters rather than use a
// string literal.
- if (file_data.size() > 65535) {
+ if (breakdown_large_file && file_data.size() > 65535) {
+ // This has to be explicitly marked as a signed char because the generated
+ // code puts negative values in the array, and sometimes plain char is
+ // unsigned. That implicit narrowing conversion is not allowed in C++11.
+ // <http://stackoverflow.com/questions/4434140/narrowing-conversions-in-c0x-is-it-just-me-or-does-this-sound-like-a-breakin>
+ // has details on why.
printer->Print(
- "static const char descriptor[] = {\n");
+ "static const signed char descriptor[] = {\n");
printer->Indent();
// Only write 25 bytes per line.
@@ -447,26 +612,25 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
for (int i = 0; i < file_data.size();) {
for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
printer->Print(
- "$char$, ",
- "char", SimpleItoa(file_data[i]));
+ "$char$, ",
+ "char", SimpleItoa(file_data[i]));
}
printer->Print(
- "\n");
+ "\n");
}
printer->Outdent();
printer->Print(
- "};\n");
+ "};\n");
printer->Print(
- "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n",
- "size", SimpleItoa(file_data.size()));
+ "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n",
+ "size", SimpleItoa(file_data.size()));
} else {
-
printer->Print(
"::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
-
+
// Only write 40 bytes per line.
static const int kBytesPerLine = 40;
for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
@@ -474,11 +638,10 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
"data",
EscapeTrigraphs(
CEscape(file_data.substr(i, kBytesPerLine))));
- }
- printer->Print(
- ", $size$);\n",
+ }
+ printer->Print(
+ ", $size$);\n",
"size", SimpleItoa(file_data.size()));
-
}
// Call MessageFactory::InternalRegisterGeneratedFile().
@@ -548,8 +711,40 @@ void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
}
}
-void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer) {
- string filename_identifier = FilenameIdentifier(file_->name());
+void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
+ ForwardDeclarations decls;
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ FileGenerator dependency(file_->dependency(i), options_);
+ dependency.FillForwardDeclarations(&decls);
+ }
+ FillForwardDeclarations(&decls);
+ decls.Print(printer);
+}
+
+void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) {
+ for (int i = 0; i < file_->public_dependency_count(); i++) {
+ FileGenerator dependency(file_->public_dependency(i), options_);
+ dependency.FillForwardDeclarations(decls);
+ }
+ for (int i = 0; i < package_parts_.size(); i++) {
+ decls = decls->AddOrGetNamespace(package_parts_[i]);
+ }
+ // Generate enum definitions.
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->FillEnumForwardDeclarations(&decls->enums());
+ }
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ enum_generators_[i]->FillForwardDeclaration(&decls->enums());
+ }
+ // Generate forward declarations of classes.
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->FillMessageForwardDeclarations(
+ &decls->classes());
+ }
+}
+
+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"
@@ -564,8 +759,8 @@ void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer) {
"filename_identifier", filename_identifier);
}
-void FileGenerator::GenerateBottomHeaderGuard(io::Printer* printer) {
- string filename_identifier = FilenameIdentifier(file_->name());
+void FileGenerator::GenerateBottomHeaderGuard(
+ io::Printer* printer, const string& filename_identifier) {
printer->Print(
"#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
"filename_identifier", filename_identifier);
@@ -696,9 +891,13 @@ void FileGenerator::GenerateGlobalStateFunctionDeclarations(
}
void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) {
- // Generate forward declarations of classes.
+ set<string> classes;
for (int i = 0; i < file_->message_type_count(); i++) {
- message_generators_[i]->GenerateMessageForwardDeclaration(printer);
+ message_generators_[i]->FillMessageForwardDeclarations(&classes);
+ }
+ for (set<string>::const_iterator it = classes.begin(), end = classes.end();
+ it != end; ++it) {
+ printer->Print("class $classname$;\n", "classname", it->c_str());
}
}
@@ -804,10 +1003,6 @@ void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
// Methods of the dependent base class must always be inline in the header.
message_generators_[i]->GenerateDependentInlineMethods(printer);
}
-
- printer->Print(
- "\n"
- "// @@protoc_insertion_point(namespace_scope)\n");
}
void FileGenerator::GenerateProto2NamespaceEnumSpecializations(
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h
index e68f67bb..29cdaea5 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -69,10 +69,14 @@ class FileGenerator {
const Options& options);
~FileGenerator();
- void GenerateHeader(io::Printer* printer);
+ void GenerateProtoHeader(io::Printer* printer);
+ void GeneratePBHeader(io::Printer* printer);
void GenerateSource(io::Printer* printer);
private:
+ // Internal type used by GenerateForwardDeclarations (defined in file.cc).
+ class ForwardDeclarations;
+
// Generate the BuildDescriptors() procedure, which builds all descriptors
// for types defined in the file.
void GenerateBuildDescriptors(io::Printer* printer);
@@ -80,9 +84,19 @@ class FileGenerator {
void GenerateNamespaceOpeners(io::Printer* printer);
void GenerateNamespaceClosers(io::Printer* printer);
+ // For other imports, generates their forward-declarations.
+ void GenerateForwardDeclarations(io::Printer* printer);
+
+ // Internal helper used by GenerateForwardDeclarations: fills 'decls'
+ // with all necessary forward-declarations for this file and its
+ // transient depednencies.
+ void FillForwardDeclarations(ForwardDeclarations* decls);
+
// Generates top or bottom of a header file.
- void GenerateTopHeaderGuard(io::Printer* printer);
- void GenerateBottomHeaderGuard(io::Printer* printer);
+ void GenerateTopHeaderGuard(io::Printer* printer,
+ const string& filename_identifier);
+ void GenerateBottomHeaderGuard(io::Printer* printer,
+ const string& filename_identifier);
// Generates #include directives.
void GenerateLibraryIncludes(io::Printer* printer);
@@ -92,10 +106,20 @@ class FileGenerator {
void GenerateGlobalStateFunctionDeclarations(io::Printer* printer);
// Generates types for classes.
- void GenerateMessageForwardDeclarations(io::Printer* printer);
void GenerateMessageDefinitions(io::Printer* printer);
+ // Generates forward-declarations for just this file's classes. This is
+ // used for .pb.h headers, but not in proto_h mode.
+ void GenerateMessageForwardDeclarations(io::Printer* printer);
+
+ // Fills in types for forward declarations. This is used internally, and
+ // also by other FileGenerators to determine imports' declarations.
+ void FillMessageForwardDeclarations(ForwardDeclarations* decls);
+ void FillMessageDefinitions(ForwardDeclarations* decls);
+
// Generates enum definitions.
+ void GenerateEnumForwardDeclarations(io::Printer* printer);
+ void FillEnumForwardDeclarations(ForwardDeclarations* decls);
void GenerateEnumDefinitions(io::Printer* printer);
// Generates generic service definitions.
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index 99416372..781526b5 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -100,16 +100,23 @@ bool CppGenerator::Generate(const FileDescriptor* file,
string basename = StripProto(file->name());
- basename.append(".pb");
FileGenerator file_generator(file, file_options);
- // Generate header.
+ // Generate header(s).
+ if (file_options.proto_h) {
+ google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(basename + ".proto.h"));
+ io::Printer printer(output.get(), '$');
+ file_generator.GenerateProtoHeader(&printer);
+ }
+
+ basename.append(".pb");
{
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(basename + ".h"));
io::Printer printer(output.get(), '$');
- file_generator.GenerateHeader(&printer);
+ file_generator.GeneratePBHeader(&printer);
}
// Generate cc file.
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 0f3688d0..09845458 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -39,6 +39,7 @@
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
@@ -68,7 +69,7 @@ const char* const kKeywordList[] = {
"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", "nullptr", "operator", "or",
+ "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",
@@ -174,6 +175,14 @@ string SuperClassName(const Descriptor* descriptor) {
"::google::protobuf::Message" : "::google::protobuf::MessageLite";
}
+string DependentBaseDownCast() {
+ return "reinterpret_cast<T*>(this)->";
+}
+
+string DependentBaseConstDownCast() {
+ return "reinterpret_cast<const T*>(this)->";
+}
+
string FieldName(const FieldDescriptor* field) {
string result = field->name();
LowerString(&result);
@@ -208,6 +217,19 @@ string FieldConstantName(const FieldDescriptor *field) {
}
bool IsFieldDependent(const FieldDescriptor* field) {
+ if (field->containing_oneof() != NULL &&
+ field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ return true;
+ }
+ if (field->is_map()) {
+ const Descriptor* map_descriptor = field->message_type();
+ for (int i = 0; i < map_descriptor->field_count(); i++) {
+ if (IsFieldDependent(map_descriptor->field(i))) {
+ return true;
+ }
+ }
+ return false;
+ }
if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
return false;
}
@@ -578,6 +600,94 @@ bool IsAnyMessage(const Descriptor* descriptor) {
descriptor->file()->name() == kAnyProtoFile;
}
+enum Utf8CheckMode {
+ STRICT = 0, // Parsing will fail if non UTF-8 data is in string fields.
+ VERIFY = 1, // Only log an error but parsing will succeed.
+ NONE = 2, // No UTF-8 check.
+};
+
+// Which level of UTF-8 enforcemant is placed on this file.
+static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field) {
+ if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+ return STRICT;
+ } else if (field->file()->options().optimize_for() !=
+ FileOptions::LITE_RUNTIME) {
+ return VERIFY;
+ } else {
+ return NONE;
+ }
+}
+
+static void GenerateUtf8CheckCode(const FieldDescriptor* field,
+ 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)) {
+ case STRICT: {
+ if (for_parse) {
+ printer->Print("DO_(");
+ }
+ printer->Print(
+ "::google::protobuf::internal::WireFormatLite::$function$(\n",
+ "function", strict_function);
+ printer->Indent();
+ printer->Print(variables, parameters);
+ if (for_parse) {
+ printer->Print("::google::protobuf::internal::WireFormatLite::PARSE,\n");
+ } else {
+ printer->Print("::google::protobuf::internal::WireFormatLite::SERIALIZE,\n");
+ }
+ printer->Print("\"$full_name$\")", "full_name", field->full_name());
+ if (for_parse) {
+ printer->Print(")");
+ }
+ printer->Print(";\n");
+ printer->Outdent();
+ break;
+ }
+ case VERIFY: {
+ printer->Print(
+ "::google::protobuf::internal::WireFormat::$function$(\n",
+ "function", verify_function);
+ printer->Indent();
+ printer->Print(variables, parameters);
+ if (for_parse) {
+ printer->Print("::google::protobuf::internal::WireFormat::PARSE,\n");
+ } else {
+ printer->Print("::google::protobuf::internal::WireFormat::SERIALIZE,\n");
+ }
+ printer->Print("\"$full_name$\");\n", "full_name", field->full_name());
+ printer->Outdent();
+ break;
+ }
+ case NONE:
+ break;
+ }
+}
+
+void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
+ bool for_parse,
+ const map<string, string>& variables,
+ const char* parameters,
+ io::Printer* printer) {
+ GenerateUtf8CheckCode(field, for_parse, variables, parameters,
+ "VerifyUtf8String", "VerifyUTF8StringNamedField",
+ printer);
+}
+
+void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
+ bool for_parse,
+ const map<string, string>& variables,
+ const char* parameters,
+ io::Printer* printer) {
+ GenerateUtf8CheckCode(field, for_parse, variables, parameters,
+ "VerifyUtf8Cord", "VerifyUTF8CordNamedField",
+ printer);
+}
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 4bbf8303..985cb04c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -70,8 +70,15 @@ string ClassName(const EnumDescriptor* enum_descriptor, bool qualified);
// This is a class name, like "ProtoName_InternalBase".
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);
+// Returns a string that down-casts from the dependent base class to the
+// derived class.
+string DependentBaseDownCast();
+string DependentBaseConstDownCast();
+
// Get the (unqualified) name that should be used for this field in C++ code.
// The name is coerced to lower-case to emulate proto1 behavior. People
// should be using lowercase-with-underscores style for proto field names
@@ -195,11 +202,6 @@ inline bool HasGenericServices(const FileDescriptor* file) {
file->options().cc_generic_services();
}
-// Should string fields in this file verify that their contents are UTF-8?
-inline bool HasUtf8Verification(const FileDescriptor* file) {
- return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
-}
-
// 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.
@@ -263,6 +265,20 @@ inline bool SupportsArenas(const FieldDescriptor* field) {
bool IsAnyMessage(const FileDescriptor* descriptor);
bool IsAnyMessage(const Descriptor* 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);
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index 0ff0d27c..25acc61b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -100,8 +100,9 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
MapFieldGenerator::
MapFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options)
- : descriptor_(descriptor) {
+ const Options& options)
+ : descriptor_(descriptor),
+ dependent_field_(options.proto_h && IsFieldDependent(descriptor)) {
SetMessageVariables(descriptor, &variables_, options);
}
@@ -152,7 +153,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
void MapFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
- printer->Print(variables_, "$name$_.Clear();\n");
+ map<string, string> variables(variables_);
+ variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
+ printer->Print(variables, "$this_message$$name$_.Clear();\n");
}
void MapFieldGenerator::
@@ -231,6 +234,20 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
"}\n");
}
+ const FieldDescriptor* key_field =
+ descriptor_->message_type()->FindFieldByName("key");
+ if (key_field->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ key_field, 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);
+ }
+
// If entry is allocated by arena, its desctructor should be avoided.
if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
@@ -258,7 +275,30 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
" entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
" ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
- " $number$, *entry, output);\n"
+ " $number$, *entry, output);\n");
+
+ printer->Indent();
+ printer->Indent();
+
+ const FieldDescriptor* key_field =
+ descriptor_->message_type()->FindFieldByName("key");
+ 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);
+ }
+ if (value_field->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ value_field, false, variables_,
+ "it->second.data(), it->second.length(),\n", printer);
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+
+ printer->Print(
" }\n");
// If entry is allocated by arena, its desctructor should be avoided.
@@ -293,7 +333,29 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
" entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
" target = ::google::protobuf::internal::WireFormatLite::\n"
" Write$declared_type$NoVirtualToArray(\n"
- " $number$, *entry, target);\n"
+ " $number$, *entry, target);\n");
+
+ printer->Indent();
+ printer->Indent();
+
+ const FieldDescriptor* key_field =
+ descriptor_->message_type()->FindFieldByName("key");
+ 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);
+ }
+ if (value_field->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ value_field, false, variables_,
+ "it->second.data(), it->second.length(),\n", printer);
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
" }\n");
// If entry is allocated by arena, its desctructor should be avoided.
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h
index d27d4851..5e205623 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h
@@ -63,6 +63,7 @@ class MapFieldGenerator : public FieldGenerator {
private:
const FieldDescriptor* descriptor_;
+ const bool dependent_field_;
map<string, string> variables_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index b0e38755..fc1ce962 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -39,7 +39,6 @@
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
-#include <set>
#include <utility>
#include <vector>
#include <google/protobuf/compiler/cpp/cpp_message.h>
@@ -415,31 +414,34 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
use_dependent_base_ = true;
}
}
+ if (options.proto_h && descriptor->oneof_decl_count() > 0) {
+ // Always make oneofs dependent.
+ use_dependent_base_ = true;
+ }
}
MessageGenerator::~MessageGenerator() {}
void MessageGenerator::
-GenerateMessageForwardDeclaration(io::Printer* printer) {
- printer->Print("class $classname$;\n",
- "classname", classname_);
+FillMessageForwardDeclarations(set<string>* class_names) {
+ class_names->insert(classname_);
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// map entry message doesn't need forward declaration. Since map entry
// message cannot be a top level class, we just need to avoid calling
// GenerateForwardDeclaration here.
if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
- nested_generators_[i]->GenerateMessageForwardDeclaration(printer);
+ nested_generators_[i]->FillMessageForwardDeclarations(class_names);
}
}
void MessageGenerator::
-GenerateEnumForwardDeclaration(io::Printer* printer) {
+FillEnumForwardDeclarations(set<string>* enum_names) {
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
- nested_generators_[i]->GenerateEnumForwardDeclaration(printer);
+ nested_generators_[i]->FillEnumForwardDeclarations(enum_names);
}
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
- enum_generators_[i]->GenerateForwardDeclaration(printer);
+ enum_generators_[i]->FillForwardDeclaration(enum_names);
}
}
@@ -484,13 +486,6 @@ GenerateDependentFieldAccessorDeclarations(io::Printer* printer) {
field_generators_.get(field).GenerateDependentAccessorDeclarations(printer);
printer->Print("\n");
}
- for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
- PrintFieldComment(printer, oneof);
- printer->Print(
- "void clear_$oneof_name$();\n",
- "oneof_name", oneof->name());
- }
}
void MessageGenerator::
@@ -505,7 +500,9 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
vars["constant_name"] = FieldConstantName(field);
bool dependent_field = use_dependent_base_ && IsFieldDependent(field);
- if (dependent_field) {
+ if (dependent_field &&
+ field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ !field->is_map()) {
// If this field is dependent, the dependent base class determines
// the message type from the derived class (which is a template
// parameter). This typedef is for that:
@@ -594,8 +591,8 @@ GenerateDependentFieldAccessorDefinitions(io::Printer* printer) {
vars["tmpl"] = "template<class T>\n";
vars["dependent_classname"] =
DependentBaseClassTemplateName(descriptor_) + "<T>";
- vars["this_message"] = "reinterpret_cast<T*>(this)->";
- vars["this_const_message"] = "reinterpret_cast<const T*>(this)->";
+ vars["this_message"] = DependentBaseDownCast();
+ vars["this_const_message"] = DependentBaseConstDownCast();
GenerateFieldClear(field, vars, printer);
}
@@ -721,13 +718,15 @@ GenerateFieldClear(const FieldDescriptor* field,
printer->Print(vars,
"if ($this_message$has_$name$()) {\n");
printer->Indent();
- field_generators_.get(field).GenerateClearingCode(printer);
+ field_generators_.get(field)
+ .GenerateClearingCode(printer);
printer->Print(vars,
"$this_message$clear_has_$oneof_name$();\n");
printer->Outdent();
printer->Print("}\n");
} else {
- field_generators_.get(field).GenerateClearingCode(printer);
+ field_generators_.get(field)
+ .GenerateClearingCode(printer);
if (HasFieldPresence(descriptor_->file())) {
if (!field->is_repeated()) {
printer->Print(vars,
@@ -752,6 +751,18 @@ GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) {
map<string, string> vars;
SetCommonFieldVariables(field, &vars, options_);
vars["inline"] = is_inline ? "inline " : "";
+ if (use_dependent_base_ && IsFieldDependent(field)) {
+ vars["tmpl"] = "template<class T>\n";
+ vars["dependent_classname"] =
+ DependentBaseClassTemplateName(descriptor_) + "<T>";
+ vars["this_message"] = "reinterpret_cast<T*>(this)->";
+ vars["this_const_message"] = "reinterpret_cast<const T*>(this)->";
+ } else {
+ vars["tmpl"] = "";
+ vars["dependent_classname"] = vars["classname"];
+ vars["this_message"] = "";
+ vars["this_const_message"] = "";
+ }
// Generate has_$name$() or $name$_size().
if (field->is_repeated()) {
@@ -775,10 +786,6 @@ GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) {
}
if (!use_dependent_base_ || !IsFieldDependent(field)) {
- vars["tmpl"] = "";
- vars["dependent_classname"] = vars["classname"];
- vars["this_message"] = "";
- vars["this_const_message"] = "";
GenerateFieldClear(field, vars, printer);
}
@@ -915,15 +922,32 @@ GenerateClassDefinition(io::Printer* printer) {
"}\n"
"\n");
} else {
- printer->Print(
- "inline const ::std::string& unknown_fields() const {\n"
- " return _unknown_fields_;\n"
- "}\n"
- "\n"
- "inline ::std::string* mutable_unknown_fields() {\n"
- " return &_unknown_fields_;\n"
- "}\n"
- "\n");
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(
+ "inline const ::std::string& unknown_fields() const {\n"
+ " return _unknown_fields_.Get(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"
+ "}\n"
+ "\n"
+ "inline ::std::string* mutable_unknown_fields() {\n"
+ " return _unknown_fields_.Mutable(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n"
+ " GetArenaNoVirtual());\n"
+ "}\n"
+ "\n");
+ } else {
+ printer->Print(
+ "inline const ::std::string& unknown_fields() const {\n"
+ " return _unknown_fields_.GetNoArena(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"
+ "}\n"
+ "\n"
+ "inline ::std::string* mutable_unknown_fields() {\n"
+ " return _unknown_fields_.MutableNoArena(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"
+ "}\n"
+ "\n");
+ }
}
}
@@ -1068,6 +1092,10 @@ GenerateClassDefinition(io::Printer* printer) {
}
}
uses_string_ = false;
+ if (PreserveUnknownFields(descriptor_) &&
+ !UseUnknownFieldSet(descriptor_->file())) {
+ uses_string_ = true;
+ }
for (int i = 0; i < descriptors.size(); i++) {
const FieldDescriptor* field = descriptors[i];
if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
@@ -1201,18 +1229,11 @@ GenerateClassDefinition(io::Printer* printer) {
// Generate oneof function declarations
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- if (use_dependent_base_) {
- printer->Print(
- "inline bool has_$oneof_name$() const;\n"
- "inline void clear_has_$oneof_name$();\n\n",
- "oneof_name", descriptor_->oneof_decl(i)->name());
- } else {
- printer->Print(
- "inline bool has_$oneof_name$() const;\n"
- "void clear_$oneof_name$();\n"
- "inline void clear_has_$oneof_name$();\n\n",
- "oneof_name", descriptor_->oneof_decl(i)->name());
- }
+ printer->Print(
+ "inline bool has_$oneof_name$() const;\n"
+ "void clear_$oneof_name$();\n"
+ "inline void clear_has_$oneof_name$();\n\n",
+ "oneof_name", descriptor_->oneof_decl(i)->name());
}
if (HasGeneratedMethods(descriptor_->file()) &&
@@ -1262,7 +1283,7 @@ GenerateClassDefinition(io::Printer* printer) {
"::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;\n");
} else {
printer->Print(
- "::std::string _unknown_fields_;\n"
+ "::google::protobuf::internal::ArenaStringPtr _unknown_fields_;\n"
"::google::protobuf::Arena* _arena_ptr_;\n"
"\n");
}
@@ -1919,6 +1940,13 @@ GenerateSharedConstructorCode(io::Printer* printer) {
uses_string_ ? "::google::protobuf::internal::GetEmptyString();\n" : "",
"_cached_size_ = 0;\n").c_str());
+ if (PreserveUnknownFields(descriptor_) &&
+ !UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ "_unknown_fields_.UnsafeSetDefault(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n");
+ }
+
for (int i = 0; i < descriptor_->field_count(); i++) {
if (!descriptor_->field(i)->containing_oneof()) {
field_generators_.get(descriptor_->field(i))
@@ -1955,6 +1983,22 @@ GenerateSharedDestructorCode(io::Printer* printer) {
"}\n"
"\n");
}
+
+ // Write the desctructor for _unknown_fields_ in lite runtime.
+ if (PreserveUnknownFields(descriptor_) &&
+ !UseUnknownFieldSet(descriptor_->file())) {
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(
+ "_unknown_fields_.Destroy(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n"
+ " GetArenaNoVirtual());\n");
+ } else {
+ printer->Print(
+ "_unknown_fields_.DestroyNoArena(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n");
+ }
+ }
+
// Write the destructors for each field except oneof members.
for (int i = 0; i < descriptor_->field_count(); i++) {
if (!descriptor_->field(i)->containing_oneof()) {
@@ -2463,8 +2507,16 @@ GenerateClear(io::Printer* printer) {
" mutable_unknown_fields()->Clear();\n"
"}\n");
} else {
- printer->Print(
- "mutable_unknown_fields()->clear();\n");
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(
+ "_unknown_fields_.ClearToEmpty(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n"
+ " GetArenaNoVirtual());\n");
+ } else {
+ printer->Print(
+ "_unknown_fields_.ClearToEmptyNoArena(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n");
+ }
}
}
@@ -2481,33 +2533,16 @@ GenerateOneofClear(io::Printer* printer) {
oneof_vars["oneofname"] = descriptor_->oneof_decl(i)->name();
string message_class;
- if (use_dependent_base_) {
- oneof_vars["tmpl"] = "template<class T>\n";
- oneof_vars["inline"] = "inline ";
- oneof_vars["dependent_classname"] =
- DependentBaseClassTemplateName(descriptor_) + "<T>";
- oneof_vars["this_message"] = "reinterpret_cast<T*>(this)->";
- message_class = "T::";
- } else {
- oneof_vars["tmpl"] = "";
- oneof_vars["inline"] = "";
- oneof_vars["dependent_classname"] = classname_;
- oneof_vars["this_message"] = "";
- }
-
printer->Print(oneof_vars,
- "$tmpl$"
- "$inline$"
- "void $dependent_classname$::clear_$oneofname$() {\n");
+ "void $classname$::clear_$oneofname$() {\n");
printer->Indent();
printer->Print(oneof_vars,
- "switch($this_message$$oneofname$_case()) {\n");
+ "switch($oneofname$_case()) {\n");
printer->Indent();
for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
printer->Print(
- "case $message_class$k$field_name$: {\n",
- "message_class", message_class,
+ "case k$field_name$: {\n",
"field_name", UnderscoresToCamelCase(field->name(), true));
printer->Indent();
// We clear only allocated objects in oneofs
@@ -2524,20 +2559,16 @@ GenerateOneofClear(io::Printer* printer) {
"}\n");
}
printer->Print(
- "case $message_class$$cap_oneof_name$_NOT_SET: {\n"
+ "case $cap_oneof_name$_NOT_SET: {\n"
" break;\n"
"}\n",
- "message_class", message_class,
"cap_oneof_name",
ToUpper(descriptor_->oneof_decl(i)->name()));
printer->Outdent();
printer->Print(
"}\n"
- "$this_message$_oneof_case_[$oneof_index$] = "
- "$message_class$$cap_oneof_name$_NOT_SET;\n",
- "this_message", oneof_vars["this_message"],
+ "_oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n",
"oneof_index", SimpleItoa(i),
- "message_class", message_class,
"cap_oneof_name",
ToUpper(descriptor_->oneof_decl(i)->name()));
printer->Outdent();
@@ -2612,7 +2643,7 @@ GenerateSwap(io::Printer* printer) {
printer->Print(
"_internal_metadata_.Swap(&other->_internal_metadata_);\n");
} else {
- printer->Print("_unknown_fields_.swap(other->_unknown_fields_);\n");
+ printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
}
} else {
// Still swap internal_metadata as it may contain more than just
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index 23dad10c..8e19a3f0 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -39,8 +39,8 @@
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <set>
#include <string>
-#include <vector>
#include <google/protobuf/compiler/cpp/cpp_field.h>
#include <google/protobuf/compiler/cpp/cpp_options.h>
@@ -66,9 +66,10 @@ class MessageGenerator {
// Header stuff.
- // Generate foward declarations for this class and all its nested types.
- void GenerateMessageForwardDeclaration(io::Printer* printer);
- void GenerateEnumForwardDeclaration(io::Printer* printer);
+ // Return names for foward declarations of this class and all its nested
+ // types.
+ void FillMessageForwardDeclarations(set<string>* class_names);
+ void FillEnumForwardDeclarations(set<string>* enum_names);
// Generate definitions of all nested enums (must come before class
// definitions because those classes use the enums definitions).
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index ba318d10..b4545892 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -63,6 +63,14 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
SafeFunctionName(descriptor->containing_type(),
descriptor, "release_");
(*variables)["full_name"] = descriptor->full_name();
+ if (options.proto_h && IsFieldDependent(descriptor)) {
+ (*variables)["dependent_type"] = "T::" + DependentTypeName(descriptor);
+ (*variables)["dependent_typename"] =
+ "typename T::" + DependentTypeName(descriptor);
+ } else {
+ (*variables)["dependent_type"] = FieldMessageTypeName(descriptor);
+ (*variables)["dependent_typename"] = FieldMessageTypeName(descriptor);
+ }
}
} // namespace
@@ -85,7 +93,21 @@ GeneratePrivateMembers(io::Printer* printer) const {
}
void MessageFieldGenerator::
+GenerateGetterDeclaration(io::Printer* printer) const {
+ printer->Print(variables_,
+ "const $type$& $name$() const$deprecation$;\n");
+}
+
+void MessageFieldGenerator::
GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+ if (!dependent_field_) {
+ return;
+ }
+ // 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");
}
void MessageFieldGenerator::
@@ -103,11 +125,13 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
"$type$* _slow_$release_name$()$deprecation$;\n"
"public:\n");
}
- printer->Print(variables_,
- "const $type$& $name$() const$deprecation$;\n"
- "$type$* mutable_$name$()$deprecation$;\n"
- "$type$* $release_name$()$deprecation$;\n"
- "void set_allocated_$name$($type$* $name$)$deprecation$;\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");
+ }
if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
"$type$* unsafe_arena_release_$name$()$deprecation$;\n"
@@ -123,12 +147,12 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
"void $classname$::_slow_mutable_$name$() {\n");
if (SupportsArenas(descriptor_->message_type())) {
printer->Print(variables_,
- " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
- " GetArenaNoVirtual());\n");
+ " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
} else {
printer->Print(variables_,
- " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
- " GetArenaNoVirtual());\n");
+ " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
}
printer->Print(variables_,
"}\n"
@@ -151,7 +175,7 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
if (SupportsArenas(descriptor_->message_type())) {
// NOTE: the same logic is mirrored in weak_message_field.cc. Any
// arena-related semantics changes should be made in both places.
- printer->Print(variables_,
+ printer->Print(variables_,
"void $classname$::_slow_set_allocated_$name$(\n"
" ::google::protobuf::Arena* message_arena, $type$** $name$) {\n"
" if (message_arena != NULL && \n"
@@ -189,15 +213,139 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
void MessageFieldGenerator::
GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+ if (!dependent_field_) {
+ return;
+ }
+
+ map<string, string> variables(variables_);
+ // For the CRTP base class, all mutation methods are dependent, and so
+ // they must be in the header.
+ variables["dependent_classname"] =
+ DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
+ variables["this_message"] = DependentBaseDownCast();
+ if (!variables["set_hasbit"].empty()) {
+ variables["set_hasbit"] =
+ variables["this_message"] + variables["set_hasbit"];
+ }
+ if (!variables["clear_hasbit"].empty()) {
+ variables["clear_hasbit"] =
+ variables["this_message"] + variables["clear_hasbit"];
+ }
+
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables,
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::mutable_$name$() {\n"
+ " $set_hasbit$\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " if ($name$_ == NULL) {\n"
+ " $this_message$_slow_mutable_$name$();\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $name$_;\n"
+ "}\n"
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::$release_name$() {\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " $clear_hasbit$\n"
+ " if ($this_message$GetArenaNoVirtual() != NULL) {\n"
+ " return $this_message$_slow_$release_name$();\n"
+ " } else {\n"
+ " $dependent_typename$* temp = $name$_;\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ " }\n"
+ "}\n"
+ "template <class T>\n"
+ "inline void $dependent_classname$::"
+ "set_allocated_$name$($type$* $name$) {\n"
+ " ::google::protobuf::Arena* message_arena = $this_message$GetArenaNoVirtual();\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " if (message_arena == NULL) {\n"
+ " delete $name$_;\n"
+ " }\n"
+ " if ($name$ != NULL) {\n");
+ if (SupportsArenas(descriptor_->message_type())) {
+ // If we're on an arena and the incoming message is not, simply Own() it
+ // rather than copy to the arena -- either way we need a heap dealloc,
+ // so we might as well defer it. Otherwise, if incoming message is on a
+ // different ownership domain (specific arena, or the heap) than we are,
+ // copy to our arena (or heap, as the case may be).
+ printer->Print(variables,
+ " $this_message$_slow_set_allocated_$name$(message_arena, "
+ "&$name$);\n");
+ } else {
+ printer->Print(variables,
+ " if (message_arena != NULL) {\n"
+ " message_arena->Own($name$);\n"
+ " }\n");
+ }
+ printer->Print(variables,
+ " }\n"
+ " $name$_ = $name$;\n"
+ " if ($name$) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ // TODO(dlj): move insertion points to message class.
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
+ } else {
+ printer->Print(variables,
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::mutable_$name$() {\n"
+ " $set_hasbit$\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " if ($name$_ == NULL) {\n"
+ " $name$_ = new $dependent_typename$;\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $name$_;\n"
+ "}\n"
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::$release_name$() {\n"
+ " $clear_hasbit$\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " $dependent_typename$* temp = $name$_;\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ "}\n"
+ "template <class T>\n"
+ "inline void $dependent_classname$::"
+ "set_allocated_$name$($type$* $name$) {\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " delete $name$_;\n");
+
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables,
+ " if ($name$ != NULL && static_cast< $dependent_typename$* >($name$)"
+ "->GetArena() != NULL) {\n"
+ " $dependent_typename$* new_$name$ = new $dependent_typename$;\n"
+ " new_$name$->CopyFrom(*$name$);\n"
+ " $name$ = new_$name$;\n"
+ " }\n");
+ }
+
+ printer->Print(variables,
+ " $name$_ = $name$;\n"
+ " if ($name$) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
+ }
}
void MessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ variables["inline"] = is_inline ? "inline " : "";
printer->Print(variables,
- "$inline$ const $type$& $classname$::$name$() const {\n"
+ "$inline$const $type$& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n");
PrintHandlingOptionalStaticInitializers(
@@ -206,19 +354,25 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
// Without.
" return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
+ printer->Print(variables, "}\n");
+
+ if (dependent_field_) {
+ return;
+ }
if (SupportsArenas(descriptor_)) {
printer->Print(variables,
- "}\n"
- "$inline$ $type$* $classname$::mutable_$name$() {\n"
+ "$inline$"
+ "$type$* $classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
" if ($name$_ == NULL) {\n"
- " _slow_mutable_$name$();"
+ " _slow_mutable_$name$();\n"
" }\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "$inline$ $type$* $classname$::$release_name$() {\n"
+ "$inline$"
+ "$type$* $classname$::$release_name$() {\n"
" $clear_hasbit$\n"
" if (GetArenaNoVirtual() != NULL) {\n"
" return _slow_$release_name$();\n"
@@ -228,7 +382,8 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" return temp;\n"
" }\n"
"}\n"
- "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ "$inline$ "
+ "void $classname$::set_allocated_$name$($type$* $name$) {\n"
" ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n"
" if (message_arena == NULL) {\n"
" delete $name$_;\n"
@@ -260,8 +415,8 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
"}\n");
} else {
printer->Print(variables,
- "}\n"
- "$inline$ $type$* $classname$::mutable_$name$() {\n"
+ "$inline$"
+ "$type$* $classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
" if ($name$_ == NULL) {\n"
" $name$_ = new $type$;\n"
@@ -269,13 +424,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "$inline$ $type$* $classname$::$release_name$() {\n"
+ "$inline$"
+ "$type$* $classname$::$release_name$() {\n"
" $clear_hasbit$\n"
" $type$* temp = $name$_;\n"
" $name$_ = NULL;\n"
" return temp;\n"
"}\n"
- "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ "$inline$"
+ "void $classname$::set_allocated_$name$($type$* $name$) {\n"
" delete $name$_;\n");
if (SupportsArenas(descriptor_->message_type())) {
@@ -301,15 +458,19 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
void MessageFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
+ map<string, string> variables(variables_);
+ variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
if (!HasFieldPresence(descriptor_->file())) {
// If we don't have has-bits, message presence is indicated only by ptr !=
// NULL. Thus on clear, we need to delete the object.
- printer->Print(variables_,
- "if (GetArenaNoVirtual() == NULL && $name$_ != NULL) delete $name$_;\n"
- "$name$_ = NULL;\n");
+ printer->Print(variables,
+ "if ($this_message$GetArenaNoVirtual() == NULL && "
+ "$this_message$$name$_ != NULL) delete $this_message$$name$_;\n"
+ "$this_message$$name$_ = NULL;\n");
} else {
- printer->Print(variables_,
- "if ($name$_ != NULL) $name$_->$type$::Clear();\n");
+ printer->Print(variables,
+ "if ($this_message$$name$_ != NULL) $this_message$$name$_->"
+ "$dependent_type$::Clear();\n");
}
}
@@ -370,79 +531,149 @@ GenerateByteSize(io::Printer* printer) const {
MessageOneofFieldGenerator::
MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
- : MessageFieldGenerator(descriptor, options) {
+ : MessageFieldGenerator(descriptor, options),
+ dependent_base_(options.proto_h) {
SetCommonOneofFieldVariables(descriptor, &variables_);
}
MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
+
+void MessageOneofFieldGenerator::
+GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+ // Oneof field getters must be dependent as they call default_instance().
+ // Otherwise, the logic is the same as MessageFields.
+ if (!dependent_field_) {
+ return;
+ }
+ printer->Print(variables_,
+ "const $type$& $name$() const$deprecation$;\n");
+ MessageFieldGenerator::GenerateDependentAccessorDeclarations(printer);
+}
+
+void MessageOneofFieldGenerator::
+GenerateGetterDeclaration(io::Printer* printer) const {
+ // Oneof field getters must be dependent as they call default_instance().
+ // Unlike MessageField, this means there is no (non-dependent) getter to
+ // generate.
+ if (dependent_field_) {
+ return;
+ }
+ printer->Print(variables_,
+ "const $type$& $name$() const$deprecation$;\n");
+}
+
void MessageOneofFieldGenerator::
GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+ // For the CRTP base class, all mutation methods are dependent, and so
+ // they must be in the header.
+ if (!dependent_base_) {
+ return;
+ }
+ map<string, string> variables(variables_);
+ variables["inline"] = "inline ";
+ variables["dependent_classname"] =
+ DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
+ variables["this_message"] = "reinterpret_cast<T*>(this)->";
+ // Const message access is needed for the dependent getter.
+ variables["this_const_message"] = "reinterpret_cast<const T*>(this)->";
+ variables["tmpl"] = "template <class T>\n";
+ variables["field_member"] = variables["this_message"] +
+ variables["oneof_prefix"] + variables["name"] +
+ "_";
+ InternalGenerateInlineAccessorDefinitions(variables, printer);
}
void MessageOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
+ if (dependent_base_) {
+ return;
+ }
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ variables["inline"] = is_inline ? "inline " : "";
+ variables["dependent_classname"] = variables["classname"];
+ variables["this_message"] = "";
+ variables["this_const_message"] = "";
+ variables["tmpl"] = "";
+ variables["field_member"] =
+ variables["oneof_prefix"] + variables["name"] + "_";
+ variables["dependent_type"] = variables["type"];
+ InternalGenerateInlineAccessorDefinitions(variables, printer);
+}
+
+void MessageOneofFieldGenerator::
+GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
+ map<string, string> variables(variables_);
+ variables["field_member"] =
+ variables["oneof_prefix"] + variables["name"] + "_";
+
+ //printer->Print(variables,
+}
+
+void MessageOneofFieldGenerator::
+InternalGenerateInlineAccessorDefinitions(const map<string, string>& variables,
+ io::Printer* printer) const {
+ printer->Print(variables,
+ "$tmpl$"
+ "$inline$ "
+ "const $type$& $dependent_classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return $this_const_message$has_$name$()\n"
+ " ? *$this_const_message$$oneof_prefix$$name$_\n"
+ " : $dependent_type$::default_instance();\n"
+ "}\n");
+
if (SupportsArenas(descriptor_)) {
printer->Print(variables,
- "$inline$ const $type$& $classname$::$name$() const {\n"
- " // @@protoc_insertion_point(field_get:$full_name$)\n"
- " return has_$name$() ? *$oneof_prefix$$name$_\n"
- " : $type$::default_instance();\n"
- "}\n"
- "$inline$ $type$* $classname$::mutable_$name$() {\n"
- " if (!has_$name$()) {\n"
- " clear_$oneof_name$();\n"
- " set_has_$name$();\n");
+ "$tmpl$"
+ "$inline$"
+ "$type$* $dependent_classname$::mutable_$name$() {\n"
+ " if (!$this_message$has_$name$()) {\n"
+ " $this_message$clear_$oneof_name$();\n"
+ " $this_message$set_has_$name$();\n");
if (SupportsArenas(descriptor_->message_type())) {
printer->Print(variables,
- " $oneof_prefix$$name$_ = \n"
- " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
- " GetArenaNoVirtual());\n");
+ " $field_member$ = \n"
+ " ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n"
+ " $this_message$GetArenaNoVirtual());\n");
} else {
printer->Print(variables,
- " $oneof_prefix$$name$_ = \n"
- " ::google::protobuf::Arena::Create< $type$ >(\n"
- " GetArenaNoVirtual());\n");
+ " $this_message$$oneof_prefix$$name$_ = \n"
+ " ::google::protobuf::Arena::Create< $dependent_typename$ >(\n"
+ " $this_message$GetArenaNoVirtual());\n");
}
printer->Print(variables,
" }\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
- " return $oneof_prefix$$name$_;\n"
+ " return $field_member$;\n"
"}\n"
- "$inline$ $type$* $classname$::$release_name$() {\n"
- " if (has_$name$()) {\n"
- " clear_has_$oneof_name$();\n"
- " if (GetArenaNoVirtual() != NULL) {\n"
+ "$tmpl$"
+ "$inline$"
+ "$type$* $dependent_classname$::$release_name$() {\n"
+ " if ($this_message$has_$name$()) {\n"
+ " $this_message$clear_has_$oneof_name$();\n"
+ " if ($this_message$GetArenaNoVirtual() != NULL) {\n"
// N.B.: safe to use the underlying field pointer here because we are sure
// that it is non-NULL (because has_$name$() returned true).
- " $type$* temp = new $type$;\n"
- " temp->MergeFrom(*$oneof_prefix$$name$_);\n"
- " $oneof_prefix$$name$_ = NULL;\n"
+ " $dependent_typename$* temp = new $dependent_typename$;\n"
+ " temp->MergeFrom(*$field_member$);\n"
+ " $field_member$ = NULL;\n"
" return temp;\n"
" } else {\n"
- " $type$* temp = $oneof_prefix$$name$_;\n"
- " $oneof_prefix$$name$_ = NULL;\n"
+ " $dependent_typename$* temp = $field_member$;\n"
+ " $field_member$ = NULL;\n"
" return temp;\n"
" }\n"
" } else {\n"
" return NULL;\n"
" }\n"
"}\n"
- "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n"
- " if (has_$name$()) {\n"
- " clear_has_$oneof_name$();\n"
- " $type$* temp = $oneof_prefix$$name$_;\n"
- " $oneof_prefix$$name$_ = NULL;\n"
- " return temp;\n"
- " } else {\n"
- " return NULL;\n"
- " }\n"
- "}\n"
- "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
- " clear_$oneof_name$();\n"
+ "$tmpl$"
+ "$inline$"
+ "void $dependent_classname$::"
+ "set_allocated_$name$($type$* $name$) {\n"
+ " $this_message$clear_$oneof_name$();\n"
" if ($name$) {\n");
if (SupportsArenas(descriptor_->message_type())) {
@@ -450,32 +681,42 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
// If incoming message is on the heap and we are on an arena, just Own()
// it (see above). If it's on a different arena than we are or one of us
// is on the heap, we make a copy to our arena/heap.
- " if (GetArenaNoVirtual() != NULL &&\n"
+ " if ($this_message$GetArenaNoVirtual() != NULL &&\n"
" ::google::protobuf::Arena::GetArena($name$) == NULL) {\n"
- " GetArenaNoVirtual()->Own($name$);\n"
- " } else if (GetArenaNoVirtual() !=\n"
+ " $this_message$GetArenaNoVirtual()->Own($name$);\n"
+ " } else if ($this_message$GetArenaNoVirtual() !=\n"
" ::google::protobuf::Arena::GetArena($name$)) {\n"
- " $type$* new_$name$ = \n"
- " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
- " GetArenaNoVirtual());\n"
+ " $dependent_typename$* new_$name$ = \n"
+ " ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n"
+ " $this_message$GetArenaNoVirtual());\n"
" new_$name$->CopyFrom(*$name$);\n"
" $name$ = new_$name$;\n"
" }\n");
} else {
printer->Print(variables,
- " if (GetArenaNoVirtual() != NULL) {\n"
- " GetArenaNoVirtual()->Own($name$);\n"
+ " if ($this_message$GetArenaNoVirtual() != NULL) {\n"
+ " $this_message$GetArenaNoVirtual()->Own($name$);\n"
" }\n");
}
printer->Print(variables,
- " set_has_$name$();\n"
- " $oneof_prefix$$name$_ = $name$;\n"
+ " $this_message$set_has_$name$();\n"
+ " $field_member$ = $name$;\n"
" }\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n"
- "$inline$ void $classname$::unsafe_arena_set_allocated_$name$("
- "$type$* $name$) {\n"
+ "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n"
+ " if (has_$name$()) {\n"
+ " clear_has_$oneof_name$();\n"
+ " $type$* temp = $oneof_prefix$$name$_;\n"
+ " $oneof_prefix$$name$_ = NULL;\n"
+ " return temp;\n"
+ " } else {\n"
+ " return NULL;\n"
+ " }\n"
+ "}\n"
+ "$inline$ void $classname$::unsafe_arena_set_allocated_$name$"
+ "($type$* $name$) {\n"
// We rely on the oneof clear method to free the earlier contents of this
// oneof. We can directly use the pointer we're given to set the new
// value.
@@ -489,44 +730,47 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
"}\n");
} else {
printer->Print(variables,
- "$inline$ const $type$& $classname$::$name$() const {\n"
- " // @@protoc_insertion_point(field_get:$full_name$)\n"
- " return has_$name$() ? *$oneof_prefix$$name$_\n"
- " : $type$::default_instance();\n"
- "}\n"
- "$inline$ $type$* $classname$::mutable_$name$() {\n"
- " if (!has_$name$()) {\n"
- " clear_$oneof_name$();\n"
- " set_has_$name$();\n"
- " $oneof_prefix$$name$_ = new $type$;\n"
+ "$tmpl$"
+ "$inline$"
+ "$type$* $dependent_classname$::mutable_$name$() {\n"
+ " if (!$this_message$has_$name$()) {\n"
+ " $this_message$clear_$oneof_name$();\n"
+ " $this_message$set_has_$name$();\n"
+ " $field_member$ = new $dependent_typename$;\n"
" }\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
- " return $oneof_prefix$$name$_;\n"
+ " return $field_member$;\n"
"}\n"
- "$inline$ $type$* $classname$::$release_name$() {\n"
- " if (has_$name$()) {\n"
- " clear_has_$oneof_name$();\n"
- " $type$* temp = $oneof_prefix$$name$_;\n"
- " $oneof_prefix$$name$_ = NULL;\n"
+ "$tmpl$"
+ "$inline$"
+ "$type$* $dependent_classname$::$release_name$() {\n"
+ " if ($this_message$has_$name$()) {\n"
+ " $this_message$clear_has_$oneof_name$();\n"
+ " $dependent_typename$* temp = $field_member$;\n"
+ " $field_member$ = NULL;\n"
" return temp;\n"
" } else {\n"
" return NULL;\n"
" }\n"
"}\n"
- "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
- " clear_$oneof_name$();\n"
+ "$tmpl$"
+ "$inline$"
+ "void $dependent_classname$::"
+ "set_allocated_$name$($type$* $name$) {\n"
+ " $this_message$clear_$oneof_name$();\n"
" if ($name$) {\n");
if (SupportsArenas(descriptor_->message_type())) {
printer->Print(variables,
- " if ($name$->GetArena() != NULL) {\n"
- " $type$* new_$name$ = new $type$;\n"
+ " if (static_cast< $dependent_typename$*>($name$)->"
+ "GetArena() != NULL) {\n"
+ " $dependent_typename$* new_$name$ = new $dependent_typename$;\n"
" new_$name$->CopyFrom(*$name$);\n"
" $name$ = new_$name$;\n"
" }\n");
}
printer->Print(variables,
- " set_has_$name$();\n"
- " $oneof_prefix$$name$_ = $name$;\n"
+ " $this_message$set_has_$name$();\n"
+ " $field_member$ = $name$;\n"
" }\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n");
@@ -535,14 +779,16 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
void MessageOneofFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
+ map<string, string> variables(variables_);
+ variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
- "if (GetArenaNoVirtual() == NULL) {\n"
- " delete $oneof_prefix$$name$_;\n"
+ printer->Print(variables,
+ "if ($this_message$GetArenaNoVirtual() == NULL) {\n"
+ " delete $this_message$$oneof_prefix$$name$_;\n"
"}\n");
} else {
- printer->Print(variables_,
- "delete $oneof_prefix$$name$_;\n");
+ printer->Print(variables,
+ "delete $this_message$$oneof_prefix$$name$_;\n");
}
}
@@ -562,7 +808,9 @@ GenerateConstructorCode(io::Printer* printer) const {
RepeatedMessageFieldGenerator::
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
- : descriptor_(descriptor) {
+ : descriptor_(descriptor),
+ dependent_field_(options.proto_h && IsFieldDependent(descriptor)),
+ dependent_getter_(dependent_field_ && options.safe_boundary_check) {
SetMessageVariables(descriptor, &variables_, options);
}
@@ -575,60 +823,160 @@ GeneratePrivateMembers(io::Printer* printer) const {
}
void RepeatedMessageFieldGenerator::
-GenerateDependentAccessorDeclarations(io::Printer* printer) const {
-}
-
-void RepeatedMessageFieldGenerator::
-GenerateAccessorDeclarations(io::Printer* printer) const {
+InternalGenerateTypeDependentAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "const $type$& $name$(int index) const$deprecation$;\n"
"$type$* mutable_$name$(int index)$deprecation$;\n"
"$type$* add_$name$()$deprecation$;\n");
+ if (dependent_getter_) {
+ printer->Print(variables_,
+ "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ " $name$() const$deprecation$;\n");
+ }
printer->Print(variables_,
- "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
- " $name$() const$deprecation$;\n"
"::google::protobuf::RepeatedPtrField< $type$ >*\n"
" mutable_$name$()$deprecation$;\n");
}
void RepeatedMessageFieldGenerator::
-GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+ if (dependent_getter_) {
+ printer->Print(variables_,
+ "const $type$& $name$(int index) const$deprecation$;\n");
+ }
+ if (dependent_field_) {
+ InternalGenerateTypeDependentAccessorDeclarations(printer);
+ }
}
void RepeatedMessageFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer,
- bool is_inline) const {
+GenerateAccessorDeclarations(io::Printer* printer) const {
+ if (!dependent_getter_) {
+ printer->Print(variables_,
+ "const $type$& $name$(int index) const$deprecation$;\n");
+ }
+ if (!dependent_field_) {
+ InternalGenerateTypeDependentAccessorDeclarations(printer);
+ }
+ if (!dependent_getter_) {
+ printer->Print(variables_,
+ "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ " $name$() const$deprecation$;\n");
+ }
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+ if (!dependent_field_) {
+ return;
+ }
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ // For the CRTP base class, all mutation methods are dependent, and so
+ // they must be in the header.
+ variables["dependent_classname"] =
+ DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
+ variables["this_message"] = DependentBaseDownCast();
+ variables["this_const_message"] = DependentBaseConstDownCast();
+
+ if (dependent_getter_) {
+ printer->Print(variables,
+ "template <class T>\n"
+ "inline const $type$& $dependent_classname$::$name$(int index) const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return $this_const_message$$name$_.$cppget$(index);\n"
+ "}\n");
+ }
+
+ // Generate per-element accessors:
printer->Print(variables,
- "$inline$ const $type$& $classname$::$name$(int index) const {\n"
- " // @@protoc_insertion_point(field_get:$full_name$)\n"
- " return $name$_.$cppget$(index);\n"
- "}\n"
- "$inline$ $type$* $classname$::mutable_$name$(int index) {\n"
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::mutable_$name$(int index) {\n"
+ // TODO(dlj): move insertion points
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
- " return $name$_.Mutable(index);\n"
+ " return $this_message$$name$_.Mutable(index);\n"
"}\n"
- "$inline$ $type$* $classname$::add_$name$() {\n"
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::add_$name$() {\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
- " return $name$_.Add();\n"
+ " return $this_message$$name$_.Add();\n"
"}\n");
+
+
+ if (dependent_getter_) {
+ printer->Print(variables,
+ "template <class T>\n"
+ "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ "$dependent_classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_list:$full_name$)\n"
+ " return $this_const_message$$name$_;\n"
+ "}\n");
+ }
+
+ // Generate mutable access to the entire list:
printer->Print(variables,
- "$inline$ const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
- "$classname$::$name$() const {\n"
- " // @@protoc_insertion_point(field_list:$full_name$)\n"
- " return $name$_;\n"
- "}\n"
- "$inline$ ::google::protobuf::RepeatedPtrField< $type$ >*\n"
- "$classname$::mutable_$name$() {\n"
+ "template <class T>\n"
+ "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
+ "$dependent_classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
- " return &$name$_;\n"
+ " return &$this_message$$name$_;\n"
"}\n");
}
void RepeatedMessageFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline " : "";
+
+ if (!dependent_getter_) {
+ printer->Print(variables,
+ "$inline$"
+ "const $type$& $classname$::$name$(int index) const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return $name$_.$cppget$(index);\n"
+ "}\n");
+ }
+
+ if (!dependent_field_) {
+ printer->Print(variables,
+ "$inline$"
+ "$type$* $classname$::mutable_$name$(int index) {\n"
+ // TODO(dlj): move insertion points
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $name$_.Mutable(index);\n"
+ "}\n"
+ "$inline$"
+ "$type$* $classname$::add_$name$() {\n"
+ " // @@protoc_insertion_point(field_add:$full_name$)\n"
+ " return $name$_.Add();\n"
+ "}\n");
+ }
+
+
+ if (!dependent_field_) {
+ printer->Print(variables,
+ "$inline$"
+ "::google::protobuf::RepeatedPtrField< $type$ >*\n"
+ "$classname$::mutable_$name$() {\n"
+ " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
+ " return &$name$_;\n"
+ "}\n");
+ }
+ if (!dependent_getter_) {
+ printer->Print(variables,
+ "$inline$"
+ "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ "$classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_list:$full_name$)\n"
+ " return $name$_;\n"
+ "}\n");
+ }
+}
+
+void RepeatedMessageFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
- printer->Print(variables_, "$name$_.Clear();\n");
+ map<string, string> variables(variables_);
+ variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
+ printer->Print(variables, "$this_message$$name$_.Clear();\n");
}
void RepeatedMessageFieldGenerator::
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h
index 9ddf9643..35efd0fa 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -68,6 +68,11 @@ class MessageFieldGenerator : public FieldGenerator {
void GenerateByteSize(io::Printer* printer) const;
protected:
+ void GenerateArenaManipulationCode(const map<string, string>& variables,
+ io::Printer* printer) const;
+
+ virtual void GenerateGetterDeclaration(io::Printer* printer) const;
+
const FieldDescriptor* descriptor_;
const bool dependent_field_;
map<string, string> variables_;
@@ -83,15 +88,23 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator {
~MessageOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
+ void GenerateDependentAccessorDeclarations(io::Printer* printer) const;
void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const;
- void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {}
+ void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
+ protected:
+ void GenerateGetterDeclaration(io::Printer* printer) const;
+
private:
+ void InternalGenerateInlineAccessorDefinitions(
+ const map<string, string>& variables, io::Printer* printer) const;
+
+ const bool dependent_base_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
};
@@ -118,7 +131,12 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
void GenerateByteSize(io::Printer* printer) const;
private:
+ void InternalGenerateTypeDependentAccessorDeclarations(
+ io::Printer* printer) const;
+
const FieldDescriptor* descriptor_;
+ const bool dependent_field_;
+ const bool dependent_getter_;
map<string, string> variables_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 1a3896a1..6b0821a6 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -367,25 +367,19 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
" input, this->mutable_$name$()));\n");
- if (HasUtf8Verification(descriptor_->file()) &&
- descriptor_->type() == FieldDescriptor::TYPE_STRING) {
- printer->Print(variables_,
- "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
- " this->$name$().data(), this->$name$().length(),\n"
- " ::google::protobuf::internal::WireFormat::PARSE,\n"
- " \"$full_name$\");\n");
+ if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ descriptor_, true, variables_,
+ "this->$name$().data(), this->$name$().length(),\n", printer);
}
}
void StringFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
- if (HasUtf8Verification(descriptor_->file()) &&
- descriptor_->type() == FieldDescriptor::TYPE_STRING) {
- printer->Print(variables_,
- "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
- " this->$name$().data(), this->$name$().length(),\n"
- " ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
- " \"$full_name$\");\n");
+ if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ descriptor_, false, variables_,
+ "this->$name$().data(), this->$name$().length(),\n", printer);
}
printer->Print(variables_,
"::google::protobuf::internal::WireFormatLite::Write$declared_type$MaybeAliased(\n"
@@ -394,13 +388,10 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
void StringFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
- if (HasUtf8Verification(descriptor_->file()) &&
- descriptor_->type() == FieldDescriptor::TYPE_STRING) {
- printer->Print(variables_,
- "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
- " this->$name$().data(), this->$name$().length(),\n"
- " ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
- " \"$full_name$\");\n");
+ if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ descriptor_, false, variables_,
+ "this->$name$().data(), this->$name$().length(),\n", printer);
}
printer->Print(variables_,
"target =\n"
@@ -421,7 +412,8 @@ GenerateByteSize(io::Printer* printer) const {
StringOneofFieldGenerator::
StringOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
- : StringFieldGenerator(descriptor, options) {
+ : StringFieldGenerator(descriptor, options),
+ dependent_field_(options.proto_h) {
SetCommonOneofFieldVariables(descriptor, &variables_);
}
@@ -604,13 +596,29 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
void StringOneofFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
+ map<string, string> variables(variables_);
+ if (dependent_field_) {
+ variables["this_message"] = DependentBaseDownCast();
+ // This clearing code may be in the dependent base class. If the default
+ // value is an empty string, then the $default_variable$ is a global
+ // singleton. If the default is not empty, we need to down-cast to get the
+ // default value's global singleton instance. See SetStringVariables() for
+ // possible values of default_variable.
+ if (!descriptor_->default_value_string().empty()) {
+ variables["default_variable"] =
+ DependentBaseDownCast() + variables["default_variable"];
+ }
+ } else {
+ variables["this_message"] = "";
+ }
if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
- "$oneof_prefix$$name$_.Destroy($default_variable$,\n"
- " GetArenaNoVirtual());\n");
+ printer->Print(variables,
+ "$this_message$$oneof_prefix$$name$_.Destroy($default_variable$,\n"
+ " $this_message$GetArenaNoVirtual());\n");
} else {
- printer->Print(variables_,
- "$oneof_prefix$$name$_.DestroyNoArena($default_variable$);\n");
+ printer->Print(variables,
+ "$this_message$$oneof_prefix$$name$_."
+ "DestroyNoArena($default_variable$);\n");
}
}
@@ -648,13 +656,10 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
" input, this->mutable_$name$()));\n");
- if (HasUtf8Verification(descriptor_->file()) &&
- descriptor_->type() == FieldDescriptor::TYPE_STRING) {
- printer->Print(variables_,
- "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
- " this->$name$().data(), this->$name$().length(),\n"
- " ::google::protobuf::internal::WireFormat::PARSE,\n"
- " \"$full_name$\");\n");
+ if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ descriptor_, true, variables_,
+ "this->$name$().data(), this->$name$().length(),\n", printer);
}
}
@@ -664,7 +669,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
RepeatedStringFieldGenerator::
RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
- : descriptor_(descriptor) {
+ : descriptor_(descriptor) {
SetStringVariables(descriptor, &variables_, options);
}
@@ -800,14 +805,12 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
" input, this->add_$name$()));\n");
- if (HasUtf8Verification(descriptor_->file()) &&
- descriptor_->type() == FieldDescriptor::TYPE_STRING) {
- printer->Print(variables_,
- "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
- " this->$name$(this->$name$_size() - 1).data(),\n"
- " this->$name$(this->$name$_size() - 1).length(),\n"
- " ::google::protobuf::internal::WireFormat::PARSE,\n"
- " \"$full_name$\");\n");
+ if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ descriptor_, true, variables_,
+ "this->$name$(this->$name$_size() - 1).data(),\n"
+ "this->$name$(this->$name$_size() - 1).length(),\n",
+ printer);
}
}
@@ -815,14 +818,13 @@ void RepeatedStringFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
- if (HasUtf8Verification(descriptor_->file()) &&
- descriptor_->type() == FieldDescriptor::TYPE_STRING) {
- printer->Print(variables_,
- "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
- " this->$name$(i).data(), this->$name$(i).length(),\n"
- " ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
- " \"$full_name$\");\n");
+ printer->Indent();
+ if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ descriptor_, false, variables_,
+ "this->$name$(i).data(), this->$name$(i).length(),\n", printer);
}
+ printer->Outdent();
printer->Print(variables_,
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
" $number$, this->$name$(i), output);\n"
@@ -833,14 +835,13 @@ void RepeatedStringFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
- if (HasUtf8Verification(descriptor_->file()) &&
- descriptor_->type() == FieldDescriptor::TYPE_STRING) {
- printer->Print(variables_,
- " ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
- " this->$name$(i).data(), this->$name$(i).length(),\n"
- " ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
- " \"$full_name$\");\n");
+ printer->Indent();
+ if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ descriptor_, false, variables_,
+ "this->$name$(i).data(), this->$name$(i).length(),\n", printer);
}
+ printer->Outdent();
printer->Print(variables_,
" target = ::google::protobuf::internal::WireFormatLite::\n"
" Write$declared_type$ToArray($number$, this->$name$(i), target);\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h
index d1f19cd9..616e2067 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -93,6 +93,7 @@ class StringOneofFieldGenerator : public StringFieldGenerator {
void GenerateMergeFromCodedStream(io::Printer* printer) const;
private:
+ const bool dependent_field_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator);
};
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index bd1c0fde..b7b6039a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -55,7 +55,11 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/unittest_optimize_for.pb.h>
#include <google/protobuf/unittest_embed_optimize_for.pb.h>
+#if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER)
+// We exclude this large proto from cmake build because it's too large for
+// visual studio to compile (report internal errors).
#include <google/protobuf/unittest_enormous_descriptor.pb.h>
+#endif
#include <google/protobuf/unittest_no_generic_services.pb.h>
#include <google/protobuf/test_util.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
@@ -67,7 +71,9 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/testing/googletest.h>
@@ -131,6 +137,7 @@ TEST(GeneratedDescriptorTest, IdenticalDescriptors) {
generated_decsriptor_proto.DebugString());
}
+#if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER)
// Test that generated code has proper descriptors:
// Touch a descriptor generated from an enormous message to validate special
// handling for descriptors exceeding the C++ standard's recommended minimum
@@ -141,6 +148,7 @@ TEST(GeneratedDescriptorTest, EnormousDescriptor) {
EXPECT_TRUE(generated_descriptor != NULL);
}
+#endif
#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc
index e0a6c83a..95ff48ae 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc
@@ -36,10 +36,12 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/compiler/csharp/csharp_generator.h>
-#include <google/protobuf/compiler/csharp/csharp_umbrella_class.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_names.h>
+#include <google/protobuf/compiler/csharp/csharp_umbrella_class.h>
using google::protobuf::internal::scoped_ptr;
@@ -48,9 +50,39 @@ namespace protobuf {
namespace compiler {
namespace csharp {
-std::string GetOutputFile(const google::protobuf::FileDescriptor* file, const std::string file_extension)
-{
- return GetUmbrellaClassUnqualifiedName(file) + file_extension;
+std::string GetOutputFile(
+ const google::protobuf::FileDescriptor* file,
+ const std::string file_extension,
+ const bool generate_directories,
+ const std::string base_namespace,
+ string* error) {
+ string relative_filename = GetUmbrellaClassUnqualifiedName(file) + file_extension;
+ if (!generate_directories) {
+ return relative_filename;
+ }
+ string ns = GetFileNamespace(file);
+ string namespace_suffix = ns;
+ if (!base_namespace.empty()) {
+ // Check that the base_namespace is either equal to or a leading part of
+ // the file namespace. This isn't just a simple prefix; "Foo.B" shouldn't
+ // be regarded as a prefix of "Foo.Bar". The simplest option is to add "."
+ // to both.
+ string extended_ns = ns + ".";
+ if (extended_ns.find(base_namespace + ".") != 0) {
+ *error = "Namespace " + ns + " is not a prefix namespace of base namespace " + base_namespace;
+ return ""; // This will be ignored, because we've set an error.
+ }
+ namespace_suffix = ns.substr(base_namespace.length());
+ if (namespace_suffix.find(".") == 0) {
+ namespace_suffix = namespace_suffix.substr(1);
+ }
+ }
+
+ string namespace_dir = StringReplace(namespace_suffix, ".", "/", true);
+ if (!namespace_dir.empty()) {
+ namespace_dir += "/";
+ }
+ return namespace_dir + relative_filename;
}
void GenerateFile(const google::protobuf::FileDescriptor* file,
@@ -75,16 +107,26 @@ bool Generator::Generate(
}
std::string file_extension = ".cs";
+ std::string base_namespace = "";
+ bool generate_directories = false;
for (int i = 0; i < options.size(); i++) {
if (options[i].first == "file_extension") {
file_extension = options[i].second;
+ } else if (options[i].first == "base_namespace") {
+ base_namespace = options[i].second;
+ generate_directories = true;
} else {
*error = "Unknown generator option: " + options[i].first;
return false;
}
}
- std::string filename = GetOutputFile(file, file_extension);
+ string filename_error = "";
+ std::string filename = GetOutputFile(file, file_extension, generate_directories, base_namespace, &filename_error);
+ if (!filename_error.empty()) {
+ *error = filename_error;
+ return false;
+ }
scoped_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(filename));
io::Printer printer(output.get(), '$');
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h
index 4ed17a84..e293faca 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.h
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h
@@ -101,8 +101,6 @@ std::string StringToBase64(const std::string& input);
std::string FileDescriptorToBase64(const FileDescriptor* descriptor);
-uint FixedMakeTag(const FieldDescriptor* descriptor);
-
FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
// Determines whether the given message is a map entry message, i.e. one implicitly created
diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
index 399c64e1..4b347708 100644
--- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
@@ -166,7 +166,7 @@ void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) {
// TODO(jonskeet): Consider a C#-escaping format here instead of just Base64.
std::string base64 = FileDescriptorToBase64(file_);
while (base64.size() > 60) {
- printer->Print("\"$base64$\", \n", "base64", base64.substr(0, 60));
+ printer->Print("\"$base64$\",\n", "base64", base64.substr(0, 60));
base64 = base64.substr(60);
}
printer->Print("\"$base64$\"));\n", "base64", base64);
diff --git a/src/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc
index 43eb0ed5..33c9328f 100644
--- a/src/google/protobuf/compiler/importer_unittest.cc
+++ b/src/google/protobuf/compiler/importer_unittest.cc
@@ -44,6 +44,7 @@
#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/stubs/strutil.h>
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index 0353b607..8a09f3a8 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -181,8 +181,8 @@ void EnumGenerator::Generate(io::Printer* printer) {
" internalGetValueMap() {\n"
" return internalValueMap;\n"
"}\n"
- "private static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n"
- " internalValueMap =\n"
+ "private static final com.google.protobuf.Internal.EnumLiteMap<\n"
+ " $classname$> internalValueMap =\n"
" new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
" public $classname$ findValueByNumber(int number) {\n"
" return $classname$.valueOf(number);\n"
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index 39318a19..558da968 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -35,6 +35,7 @@
#include <map>
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
index 697a07a7..2c3608c2 100644
--- a/src/google/protobuf/compiler/java/java_enum_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
@@ -35,6 +35,7 @@
#include <map>
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
diff --git a/src/google/protobuf/compiler/java/java_enum_lite.cc b/src/google/protobuf/compiler/java/java_enum_lite.cc
new file mode 100644
index 00000000..62186386
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_enum_lite.cc
@@ -0,0 +1,226 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_enum_lite.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+bool EnumHasCustomOptions(const EnumDescriptor* descriptor) {
+ if (descriptor->options().unknown_fields().field_count() > 0) return true;
+ for (int i = 0; i < descriptor->value_count(); ++i) {
+ const EnumValueDescriptor* value = descriptor->value(i);
+ if (value->options().unknown_fields().field_count() > 0) return true;
+ }
+ return false;
+}
+} // namespace
+
+EnumLiteGenerator::EnumLiteGenerator(const EnumDescriptor* descriptor,
+ bool immutable_api,
+ Context* context)
+ : descriptor_(descriptor), immutable_api_(immutable_api),
+ name_resolver_(context->GetNameResolver()) {
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ const EnumValueDescriptor* value = descriptor_->value(i);
+ const EnumValueDescriptor* canonical_value =
+ descriptor_->FindValueByNumber(value->number());
+
+ if (value == canonical_value) {
+ canonical_values_.push_back(value);
+ } else {
+ Alias alias;
+ alias.value = value;
+ alias.canonical_value = canonical_value;
+ aliases_.push_back(alias);
+ }
+ }
+}
+
+EnumLiteGenerator::~EnumLiteGenerator() {}
+
+void EnumLiteGenerator::Generate(io::Printer* printer) {
+ WriteEnumDocComment(printer, descriptor_);
+ if (HasDescriptorMethods(descriptor_)) {
+ printer->Print(
+ "public enum $classname$\n"
+ " implements com.google.protobuf.ProtocolMessageEnum {\n",
+ "classname", descriptor_->name());
+ } else {
+ printer->Print(
+ "public enum $classname$\n"
+ " implements com.google.protobuf.Internal.EnumLite {\n",
+ "classname", descriptor_->name());
+ }
+ printer->Indent();
+
+ for (int i = 0; i < canonical_values_.size(); i++) {
+ map<string, string> vars;
+ vars["name"] = canonical_values_[i]->name();
+ vars["index"] = SimpleItoa(canonical_values_[i]->index());
+ vars["number"] = SimpleItoa(canonical_values_[i]->number());
+ WriteEnumValueDocComment(printer, canonical_values_[i]);
+ if (canonical_values_[i]->options().deprecated()) {
+ printer->Print("@java.lang.Deprecated\n");
+ }
+ printer->Print(vars,
+ "$name$($index$, $number$),\n");
+ }
+
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print("UNRECOGNIZED(-1, -1),\n");
+ }
+
+ printer->Print(
+ ";\n"
+ "\n");
+
+ // -----------------------------------------------------------------
+
+ for (int i = 0; i < aliases_.size(); i++) {
+ map<string, string> vars;
+ vars["classname"] = descriptor_->name();
+ vars["name"] = aliases_[i].value->name();
+ vars["canonical_name"] = aliases_[i].canonical_value->name();
+ WriteEnumValueDocComment(printer, aliases_[i].value);
+ printer->Print(vars,
+ "public static final $classname$ $name$ = $canonical_name$;\n");
+ }
+
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ map<string, string> vars;
+ vars["name"] = descriptor_->value(i)->name();
+ vars["number"] = SimpleItoa(descriptor_->value(i)->number());
+ WriteEnumValueDocComment(printer, descriptor_->value(i));
+ printer->Print(vars,
+ "public static final int $name$_VALUE = $number$;\n");
+ }
+ printer->Print("\n");
+
+ // -----------------------------------------------------------------
+
+ printer->Print(
+ "\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");
+ }
+ printer->Print(
+ " return value;\n"
+ "}\n"
+ "\n"
+ "public static $classname$ valueOf(int value) {\n"
+ " switch (value) {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+ printer->Indent();
+
+ for (int i = 0; i < canonical_values_.size(); i++) {
+ printer->Print(
+ "case $number$: return $name$;\n",
+ "name", canonical_values_[i]->name(),
+ "number", SimpleItoa(canonical_values_[i]->number()));
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " default: return null;\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n"
+ " internalGetValueMap() {\n"
+ " return internalValueMap;\n"
+ "}\n"
+ "private static final com.google.protobuf.Internal.EnumLiteMap<\n"
+ " $classname$> internalValueMap =\n"
+ " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
+ " public $classname$ findValueByNumber(int number) {\n"
+ " return $classname$.valueOf(number);\n"
+ " }\n"
+ " };\n"
+ "\n",
+ "classname", descriptor_->name());
+
+ printer->Print(
+ "private final int value;\n\n"
+ "private $classname$(int index, int value) {\n",
+ "classname", descriptor_->name());
+ printer->Print(
+ " this.value = value;\n"
+ "}\n");
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(enum_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+bool EnumLiteGenerator::CanUseEnumValues() {
+ if (canonical_values_.size() != descriptor_->value_count()) {
+ return false;
+ }
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ if (descriptor_->value(i)->name() != canonical_values_[i]->name()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_enum_lite.h b/src/google/protobuf/compiler/java/java_enum_lite.h
new file mode 100644
index 00000000..ee2f5f7a
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_enum_lite.h
@@ -0,0 +1,99 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__
+
+#include <string>
+#include <vector>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ class ClassNameResolver; // name_resolver.h
+ }
+ }
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class EnumLiteGenerator {
+ public:
+ explicit EnumLiteGenerator(const EnumDescriptor* descriptor,
+ bool immutable_api,
+ Context* context);
+ ~EnumLiteGenerator();
+
+ void Generate(io::Printer* printer);
+
+ private:
+ const EnumDescriptor* descriptor_;
+
+ // The proto language allows multiple enum constants to have the same numeric
+ // value. Java, however, does not allow multiple enum constants to be
+ // considered equivalent. We treat the first defined constant for any
+ // given numeric value as "canonical" and the rest as aliases of that
+ // canonical value.
+ vector<const EnumValueDescriptor*> canonical_values_;
+
+ struct Alias {
+ const EnumValueDescriptor* value;
+ const EnumValueDescriptor* canonical_value;
+ };
+ vector<Alias> aliases_;
+
+ bool immutable_api_;
+
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ bool CanUseEnumValues();
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
index 3f0fa11f..c5434767 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -39,6 +39,7 @@
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_enum_field.h>
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index 00f3c601..0e24da24 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -44,6 +44,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/logging.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index 96d2545f..5392d6d7 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -310,6 +310,12 @@ inline bool SupportFieldPresence(const FileDescriptor* descriptor) {
return descriptor->syntax() != FileDescriptor::SYNTAX_PROTO3;
}
+// Whether generate classes expose public PARSER instances.
+inline bool ExposePublicParser(const FileDescriptor* descriptor) {
+ // TODO(liujisi): Mark the PARSER private in 3.1.x releases.
+ return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2;
+}
+
// Whether unknown enum values are kept (i.e., not stored in UnknownFieldSet
// but in the message and can be queried using additional getters that return
// ints.
@@ -332,6 +338,15 @@ inline bool PreserveUnknownFields(const Descriptor* descriptor) {
return descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
}
+inline bool IsAnyMessage(const Descriptor* descriptor) {
+ return descriptor->full_name() == "google.protobuf.Any";
+}
+
+inline bool CheckUtf8(const FieldDescriptor* descriptor) {
+ return descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ||
+ descriptor->file()->options().java_string_check_utf8();
+}
+
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc
index 44b86cd7..3e035c89 100644
--- a/src/google/protobuf/compiler/java/java_map_field.cc
+++ b/src/google/protobuf/compiler/java/java_map_field.cc
@@ -314,6 +314,14 @@ GenerateBuilderMembers(io::Printer* printer) const {
" internalGetMutable$capitalized_name$().getMutableMap(),\n"
" $name$ValueConverter);\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder putAll$capitalized_name$(\n"
+ " java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
+ " getMutable$capitalized_name$().putAll(values);\n"
+ " return this;\n"
+ "}\n");
if (SupportUnknownEnumValue(descriptor_->file())) {
WriteFieldDocComment(printer, descriptor_);
printer->Print(
@@ -331,6 +339,14 @@ GenerateBuilderMembers(io::Printer* printer) const {
"getMutable$capitalized_name$Value() {\n"
" return internalGetMutable$capitalized_name$().getMutableMap();\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder putAll$capitalized_name$Value(\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
+ " getMutable$capitalized_name$Value().putAll(values);\n"
+ " return this;\n"
+ "}\n");
}
} else {
WriteFieldDocComment(printer, descriptor_);
@@ -346,6 +362,14 @@ GenerateBuilderMembers(io::Printer* printer) const {
"getMutable$capitalized_name$() {\n"
" return internalGetMutable$capitalized_name$().getMutableMap();\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder putAll$capitalized_name$(\n"
+ " java.util.Map<$type_parameters$> values) {\n"
+ " getMutable$capitalized_name$().putAll(values);\n"
+ " return this;\n"
+ "}\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 cd1698f0..4fe656d3 100644
--- a/src/google/protobuf/compiler/java/java_map_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc
@@ -303,6 +303,14 @@ GenerateBuilderMembers(io::Printer* printer) const {
" copyOnWrite();\n"
" return instance.getMutable$capitalized_name$();\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder putAll$capitalized_name$(\n"
+ " java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
+ " getMutable$capitalized_name$().putAll(values);\n"
+ " return this;\n"
+ "}\n");
if (SupportUnknownEnumValue(descriptor_->file())) {
WriteFieldDocComment(printer, descriptor_);
printer->Print(
@@ -321,6 +329,14 @@ GenerateBuilderMembers(io::Printer* printer) const {
" copyOnWrite();\n"
" return instance.getMutable$capitalized_name$Value();\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder putAll$capitalized_name$Value(\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
+ " getMutable$capitalized_name$Value().putAll(values);\n"
+ " return this;\n"
+ "}\n");
}
} else {
WriteFieldDocComment(printer, descriptor_);
@@ -337,6 +353,14 @@ GenerateBuilderMembers(io::Printer* printer) const {
" copyOnWrite();\n"
" return instance.getMutable$capitalized_name$();\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "public Builder putAll$capitalized_name$(\n"
+ " java.util.Map<$type_parameters$> values) {\n"
+ " getMutable$capitalized_name$().putAll(values);\n"
+ " return this;\n"
+ "}\n");
}
}
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 09b0fd94..19ba0707 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -255,6 +255,18 @@ void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
field_generators_.get(descriptor_->field(i))
.GenerateInterfaceMembers(printer);
}
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ printer->Print(
+ "\n"
+ "public $classname$.$oneof_capitalized_name$Case "
+ "get$oneof_capitalized_name$Case();\n",
+ "oneof_capitalized_name",
+ context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->capitalized_name,
+ "classname",
+ context_->GetNameResolver()->GetImmutableClassName(
+ descriptor_));
+ }
printer->Outdent();
printer->Print("}\n");
@@ -292,8 +304,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
" com.google.protobuf.GeneratedMessage implements\n"
" $extra_interfaces$\n"
" $classname$OrBuilder {\n");
-
- builder_type = "com.google.protobuf.GeneratedMessage.Builder";
+ builder_type = "com.google.protobuf.GeneratedMessage.Builder<?>";
}
printer->Indent();
// Using builder_type, instead of Builder, prevents the Builder class from
@@ -435,6 +446,10 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
"\n");
}
+ if (IsAnyMessage(descriptor_)) {
+ GenerateAnyMethods(printer);
+ }
+
// Fields
for (int i = 0; i < descriptor_->field_count(); i++) {
printer->Print("public static final int $constant_name$ = $number$;\n",
@@ -578,9 +593,8 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
printer->Print(
"}\n"
"\n"
- "private int memoizedSerializedSize = -1;\n"
"public int getSerializedSize() {\n"
- " int size = memoizedSerializedSize;\n"
+ " int size = memoizedSize;\n"
" if (size != -1) return size;\n"
"\n"
" size = 0;\n");
@@ -612,7 +626,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
printer->Outdent();
printer->Print(
- " memoizedSerializedSize = size;\n"
+ " memoizedSize = size;\n"
" return size;\n"
"}\n"
"\n");
@@ -948,22 +962,58 @@ GenerateEqualsAndHashCode(io::Printer* printer) {
printer->Print("boolean result = true;\n");
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
- const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
- bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
- if (check_has_bits) {
+ 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",
+ "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(
- "result = result && (has$name$() == other.has$name$());\n"
- "if (has$name$()) {\n",
- "name", info->capitalized_name);
+ "case $field_number$:\n",
+ "field_number",
+ SimpleItoa(field->number()));
printer->Indent();
- }
- field_generators_.get(field).GenerateEqualsCode(printer);
- if (check_has_bits) {
+ field_generators_.get(field).GenerateEqualsCode(printer);
+ printer->Print("break;\n");
printer->Outdent();
- printer->Print(
- "}\n");
}
+ 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
@@ -1198,8 +1248,11 @@ GenerateParsingConstructor(io::Printer* printer) {
// ===================================================================
void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
printer->Print(
- "public static final com.google.protobuf.Parser<$classname$> PARSER =\n"
- " new com.google.protobuf.AbstractParser<$classname$>() {\n",
+ "$visibility$ static final com.google.protobuf.Parser<$classname$>\n"
+ " PARSER = new com.google.protobuf.AbstractParser<$classname$>() {\n",
+ "visibility",
+ ExposePublicParser(descriptor_->file()) ? "@java.lang.Deprecated public"
+ : "private",
"classname", descriptor_->name());
printer->Indent();
printer->Print(
@@ -1250,6 +1303,10 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
"\n");
printer->Print(
+ "public static com.google.protobuf.Parser<$classname$> parser() {\n"
+ " return PARSER;\n"
+ "}\n"
+ "\n"
"@java.lang.Override\n"
"public com.google.protobuf.Parser<$classname$> getParserForType() {\n"
" return PARSER;\n"
@@ -1269,6 +1326,50 @@ void ImmutableMessageGenerator::GenerateInitializers(io::Printer* printer) {
}
+void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) {
+ printer->Print(
+ "private static String getTypeUrl(\n"
+ " com.google.protobuf.Descriptors.Descriptor descriptor) {\n"
+ " return \"type.googleapis.com/\" + descriptor.getFullName();\n"
+ "}\n"
+ "\n"
+ "public static <T extends com.google.protobuf.Message> Any pack(\n"
+ " T message) {\n"
+ " return Any.newBuilder()\n"
+ " .setTypeUrl(getTypeUrl(message.getDescriptorForType()))\n"
+ " .setValue(message.toByteString())\n"
+ " .build();\n"
+ "}\n"
+ "\n"
+ "public <T extends com.google.protobuf.Message> boolean is(\n"
+ " java.lang.Class<T> clazz) {\n"
+ " T defaultInstance =\n"
+ " com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
+ " return getTypeUrl().equals(\n"
+ " getTypeUrl(defaultInstance.getDescriptorForType()));\n"
+ "}\n"
+ "\n"
+ "private volatile com.google.protobuf.Message cachedUnpackValue;\n"
+ "\n"
+ "public <T extends com.google.protobuf.Message> T unpack(\n"
+ " java.lang.Class<T> clazz)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " if (!is(clazz)) {\n"
+ " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
+ " \"Type of the Any messsage does not match the given class.\");\n"
+ " }\n"
+ " if (cachedUnpackValue != null) {\n"
+ " return (T) cachedUnpackValue;\n"
+ " }\n"
+ " T defaultInstance =\n"
+ " com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
+ " T result = (T) defaultInstance.getParserForType()\n"
+ " .parseFrom(getValue());\n"
+ " cachedUnpackValue = result;\n"
+ " return result;\n"
+ "}\n");
+}
+
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h
index c3c37765..be5bfb07 100644
--- a/src/google/protobuf/compiler/java/java_message.h
+++ b/src/google/protobuf/compiler/java/java_message.h
@@ -122,6 +122,7 @@ class ImmutableMessageGenerator : public MessageGenerator {
void GenerateEqualsAndHashCode(io::Printer* printer);
void GenerateParser(io::Printer* printer);
void GenerateParsingConstructor(io::Printer* printer);
+ void GenerateAnyMethods(io::Printer* printer);
Context* context_;
ClassNameResolver* name_resolver_;
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index b180b4a7..b5f8e626 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -452,11 +452,11 @@ GenerateParsingCode(io::Printer* printer) const {
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
- "$name$_ = input.readGroup($number$, $type$.PARSER,\n"
+ "$name$_ = input.readGroup($number$, $type$.parser(),\n"
" extensionRegistry);\n");
} else {
printer->Print(variables_,
- "$name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n");
+ "$name$_ = input.readMessage($type$.parser(), extensionRegistry);\n");
}
printer->Print(variables_,
@@ -736,11 +736,12 @@ GenerateParsingCode(io::Printer* printer) const {
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
- "$oneof_name$_ = input.readGroup($number$, $type$.PARSER,\n"
+ "$oneof_name$_ = input.readGroup($number$, $type$.parser(),\n"
" extensionRegistry);\n");
} else {
printer->Print(variables_,
- "$oneof_name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n");
+ "$oneof_name$_ =\n"
+ " input.readMessage($type$.parser(), extensionRegistry);\n");
}
printer->Print(variables_,
@@ -1232,11 +1233,11 @@ GenerateParsingCode(io::Printer* printer) const {
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
- "$name$_.add(input.readGroup($number$, $type$.PARSER,\n"
+ "$name$_.add(input.readGroup($number$, $type$.parser(),\n"
" extensionRegistry));\n");
} else {
printer->Print(variables_,
- "$name$_.add(input.readMessage($type$.PARSER, extensionRegistry));\n");
+ "$name$_.add(input.readMessage($type$.parser(), extensionRegistry));\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 8332202c..356520ec 100644
--- a/src/google/protobuf/compiler/java/java_message_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc
@@ -310,11 +310,11 @@ GenerateParsingCode(io::Printer* printer) const {
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
- "$name$_ = input.readGroup($number$, $type$.PARSER,\n"
+ "$name$_ = input.readGroup($number$, $type$.parser(),\n"
" extensionRegistry);\n");
} else {
printer->Print(variables_,
- "$name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n");
+ "$name$_ = input.readMessage($type$.parser(), extensionRegistry);\n");
}
printer->Print(variables_,
@@ -521,11 +521,12 @@ GenerateParsingCode(io::Printer* printer) const {
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
- "$oneof_name$_ = input.readGroup($number$, $type$.PARSER,\n"
+ "$oneof_name$_ = input.readGroup($number$, $type$.parser(),\n"
" extensionRegistry);\n");
} else {
printer->Print(variables_,
- "$oneof_name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n");
+ "$oneof_name$_ =\n"
+ " input.readMessage($type$.parser(), extensionRegistry);\n");
}
printer->Print(variables_,
@@ -885,11 +886,12 @@ GenerateParsingCode(io::Printer* printer) const {
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
- "$name$_.add(input.readGroup($number$, $type$.PARSER,\n"
+ "$name$_.add(input.readGroup($number$, $type$.parser(),\n"
" extensionRegistry));\n");
} else {
printer->Print(variables_,
- "$name$_.add(input.readMessage($type$.PARSER, extensionRegistry));\n");
+ "$name$_.add(\n"
+ " input.readMessage($type$.parser(), extensionRegistry));\n");
}
}
diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc
index 3accee92..8b6c75b8 100644
--- a/src/google/protobuf/compiler/java/java_message_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -45,7 +45,7 @@
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
-#include <google/protobuf/compiler/java/java_enum.h>
+#include <google/protobuf/compiler/java/java_enum_lite.h>
#include <google/protobuf/compiler/java/java_extension.h>
#include <google/protobuf/compiler/java/java_generator_factory.h>
#include <google/protobuf/compiler/java/java_helpers.h>
@@ -143,6 +143,17 @@ void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) {
field_generators_.get(descriptor_->field(i))
.GenerateInterfaceMembers(printer);
}
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ printer->Print(
+ "\n"
+ "public $classname$.$oneof_capitalized_name$Case "
+ "get$oneof_capitalized_name$Case();\n",
+ "oneof_capitalized_name",
+ context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->capitalized_name,
+ "classname",
+ context_->GetNameResolver()->GetImmutableClassName(descriptor_));
+ }
printer->Outdent();
printer->Print("}\n");
@@ -190,7 +201,7 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
// Nested types
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
- EnumGenerator(descriptor_->enum_type(i), true, context_)
+ EnumLiteGenerator(descriptor_->enum_type(i), true, context_)
.Generate(printer);
}
@@ -321,12 +332,12 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
printer->Print(
"protected final Object dynamicMethod(\n"
" com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n"
- " Object... args) {\n"
+ " Object arg0, Object arg1) {\n"
" switch (method) {\n"
" case PARSE_PARTIAL_FROM: {\n"
" return new $classname$("
- " (com.google.protobuf.CodedInputStream) args[0],\n"
- " (com.google.protobuf.ExtensionRegistryLite) args[1]);\n"
+ " (com.google.protobuf.CodedInputStream) arg0,\n"
+ " (com.google.protobuf.ExtensionRegistryLite) arg1);\n"
" }\n"
" case NEW_INSTANCE: {\n"
" return new $classname$(\n"
@@ -370,7 +381,25 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
printer->Outdent();
printer->Print(
- "}\n");
+ "}\n"
+ "case GET_DEFAULT_INSTANCE: {\n"
+ " return DEFAULT_INSTANCE;\n"
+ "}\n"
+ "case GET_PARSER: {\n"
+ // Generally one would use the lazy initialization holder pattern for
+ // manipulating static fields but that has exceptional cost on Android as
+ // it will generate an extra class for every message. Instead, use the
+ // double-check locking pattern which works just as well.
+ " if (PARSER == null) {"
+ " synchronized ($classname$.class) {\n"
+ " if (PARSER == null) {\n"
+ " PARSER = new DefaultInstanceBasedParser(DEFAULT_INSTANCE);\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " return PARSER;\n"
+ "}\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
printer->Outdent();
printer->Outdent();
@@ -413,18 +442,6 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
GenerateParser(printer);
- // LITE_RUNTIME uses this to implement the *ForType methods at the
- // GeneratedMessageLite level.
- printer->Print(
- "static {\n"
- " com.google.protobuf.GeneratedMessageLite.onLoad(\n"
- " $classname$.class, new com.google.protobuf.GeneratedMessageLite\n"
- " .PrototypeHolder<$classname$, Builder>(\n"
- " DEFAULT_INSTANCE, PARSER));"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
-
// Extensions must be declared after the DEFAULT_INSTANCE is initialized
// because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
// the outer class's FileDescriptor.
@@ -554,54 +571,54 @@ GenerateParseFromMethods(io::Printer* printer) {
"public static $classname$ parseFrom(\n"
" com.google.protobuf.ByteString data)\n"
" throws com.google.protobuf.InvalidProtocolBufferException {\n"
- " return PARSER.parseFrom(data);\n"
+ " return parser().parseFrom(data);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.ByteString data,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws com.google.protobuf.InvalidProtocolBufferException {\n"
- " return PARSER.parseFrom(data, extensionRegistry);\n"
+ " return parser().parseFrom(data, extensionRegistry);\n"
"}\n"
"public static $classname$ parseFrom(byte[] data)\n"
" throws com.google.protobuf.InvalidProtocolBufferException {\n"
- " return PARSER.parseFrom(data);\n"
+ " return parser().parseFrom(data);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" byte[] data,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws com.google.protobuf.InvalidProtocolBufferException {\n"
- " return PARSER.parseFrom(data, extensionRegistry);\n"
+ " return parser().parseFrom(data, extensionRegistry);\n"
"}\n"
"public static $classname$ parseFrom(java.io.InputStream input)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseFrom(input);\n"
+ " return parser().parseFrom(input);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" java.io.InputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseFrom(input, extensionRegistry);\n"
+ " return parser().parseFrom(input, extensionRegistry);\n"
"}\n"
"public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseDelimitedFrom(input);\n"
+ " return parser().parseDelimitedFrom(input);\n"
"}\n"
"public static $classname$ parseDelimitedFrom(\n"
" java.io.InputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseDelimitedFrom(input, extensionRegistry);\n"
+ " return parser().parseDelimitedFrom(input, extensionRegistry);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.CodedInputStream input)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseFrom(input);\n"
+ " return parser().parseFrom(input);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.CodedInputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseFrom(input, extensionRegistry);\n"
+ " return parser().parseFrom(input, extensionRegistry);\n"
"}\n"
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
@@ -652,7 +669,7 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized(
"if (isInitialized == 1) return DEFAULT_INSTANCE;\n"
"if (isInitialized == 0) return null;\n"
"\n"
- "boolean shouldMemoize = ((Boolean) args[0]).booleanValue();\n");
+ "boolean shouldMemoize = ((Boolean) arg0).booleanValue();\n");
// Check that all required fields in this message are set.
// TODO(kenton): We can optimize this when we switch to putting all the
@@ -778,7 +795,7 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMakeImmutable(
.GenerateDynamicMethodMakeImmutableCode(printer);
}
printer->Print(
- "return null;");
+ "return null;\n");
}
// ===================================================================
@@ -786,7 +803,7 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMakeImmutable(
void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuilder(
io::Printer* printer) {
printer->Print(
- "return new Builder();");
+ "return new Builder();\n");
}
// ===================================================================
@@ -796,9 +813,8 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom(
printer->Print(
// Optimization: If other is the default instance, we know none of its
// fields are set so we can skip the merge.
- "Object arg = args[0];\n"
- "if (arg == $classname$.getDefaultInstance()) return this;\n"
- "$classname$ other = ($classname$) arg;\n",
+ "if (arg0 == $classname$.getDefaultInstance()) return this;\n"
+ "$classname$ other = ($classname$) arg0;\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -1151,9 +1167,11 @@ GenerateParsingConstructor(io::Printer* printer) {
// ===================================================================
void ImmutableMessageLiteGenerator::GenerateParser(io::Printer* printer) {
printer->Print(
- "public static final com.google.protobuf.Parser<$classname$> PARSER =\n"
- " new DefaultInstanceBasedParser(DEFAULT_INSTANCE);\n"
- "\n",
+ "private static volatile com.google.protobuf.Parser<$classname$> PARSER;\n"
+ "\n"
+ "public static com.google.protobuf.Parser<$classname$> parser() {\n"
+ " return DEFAULT_INSTANCE.getParserForType();\n"
+ "}\n",
"classname", descriptor_->name());
}
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index 7bebe12a..178bbe19 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -35,6 +35,7 @@
#include <map>
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
index 217ff9b6..392333b8 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
@@ -35,6 +35,7 @@
#include <map>
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
diff --git a/src/google/protobuf/compiler/java/java_service.cc b/src/google/protobuf/compiler/java/java_service.cc
index 7baead15..11bfc12d 100644
--- a/src/google/protobuf/compiler/java/java_service.cc
+++ b/src/google/protobuf/compiler/java/java_service.cc
@@ -39,7 +39,6 @@
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/compiler/java/java_name_resolver.h>
#include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
index 68e863cc..72ebaeca 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -36,6 +36,7 @@
#include <map>
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
@@ -77,6 +78,10 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
" if (value == null) {\n"
" throw new NullPointerException();\n"
" }\n";
+ (*variables)["writeString"] =
+ "com.google.protobuf.GeneratedMessage.writeString";
+ (*variables)["computeStringSize"] =
+ "com.google.protobuf.GeneratedMessage.computeStringSize";
// TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
// by the proto compiler
@@ -126,10 +131,6 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
GenerateSetBitToLocal(messageBitIndex);
}
-bool CheckUtf8(const FieldDescriptor* descriptor) {
- return descriptor->file()->options().java_string_check_utf8();
-}
-
} // namespace
// ===================================================================
@@ -433,7 +434,7 @@ void ImmutableStringFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($is_field_present_message$) {\n"
- " output.writeBytes($number$, get$capitalized_name$Bytes());\n"
+ " $writeString$(output, $number$, $name$_);\n"
"}\n");
}
@@ -441,8 +442,7 @@ void ImmutableStringFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($is_field_present_message$) {\n"
- " size += com.google.protobuf.CodedOutputStream\n"
- " .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
+ " size += $computeStringSize$($number$, $name$_);\n"
"}\n");
}
@@ -689,7 +689,7 @@ void ImmutableStringOneofFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($has_oneof_case_message$) {\n"
- " output.writeBytes($number$, get$capitalized_name$Bytes());\n"
+ " $writeString$(output, $number$, $oneof_name$_);\n"
"}\n");
}
@@ -697,8 +697,7 @@ void ImmutableStringOneofFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($has_oneof_case_message$) {\n"
- " size += com.google.protobuf.CodedOutputStream\n"
- " .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
+ " size += $computeStringSize$($number$, $oneof_name$_);\n"
"}\n");
}
@@ -1007,12 +1006,12 @@ GenerateSerializationCode(io::Printer* printer) const {
" output.writeRawVarint32($name$MemoizedSerializedSize);\n"
"}\n"
"for (int i = 0; i < $name$_.size(); i++) {\n"
- " output.write$capitalized_type$NoTag($name$_.get(i));\n"
+ " writeStringNoTag(output, $name$_.getRaw(i));\n"
"}\n");
} else {
printer->Print(variables_,
"for (int i = 0; i < $name$_.size(); i++) {\n"
- " output.writeBytes($number$, $name$_.getByteString(i));\n"
+ " $writeString$(output, $number$, $name$_.getRaw(i));\n"
"}\n");
}
}
@@ -1026,8 +1025,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < $name$_.size(); i++) {\n"
- " dataSize += com.google.protobuf.CodedOutputStream\n"
- " .computeBytesSizeNoTag($name$_.getByteString(i));\n"
+ " dataSize += computeStringSizeNoTag($name$_.getRaw(i));\n"
"}\n");
printer->Print(
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 51bb245c..092e3c29 100644
--- a/src/google/protobuf/compiler/java/java_string_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc
@@ -36,6 +36,7 @@
#include <map>
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
@@ -64,7 +65,8 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
map<string, string>* variables) {
SetCommonFieldVariables(descriptor, info, variables);
- (*variables)["empty_list"] = "emptyLazyStringArrayList()";
+ (*variables)["empty_list"] =
+ "com.google.protobuf.GeneratedMessageLite.emptyProtobufList()";
(*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
(*variables)["default_init"] =
@@ -101,7 +103,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*variables)["clear_has_field_bit_message"] = "";
(*variables)["is_field_present_message"] =
- "!get" + (*variables)["capitalized_name"] + "Bytes().isEmpty()";
+ "!get" + (*variables)["capitalized_name"] + ".isEmpty()";
}
// For repeated builders, the underlying list tracks mutability state.
@@ -113,10 +115,6 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
GenerateSetBitToLocal(messageBitIndex);
}
-bool CheckUtf8(const FieldDescriptor* descriptor) {
- return descriptor->file()->options().java_string_check_utf8();
-}
-
} // namespace
// ===================================================================
@@ -144,8 +142,9 @@ int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
return 0;
}
-// A note about how strings are handled. This code used to just store a String
-// in the Message. This had two issues:
+// A note about how strings are handled. In the SPEED and CODE_SIZE runtimes,
+// strings are not stored as java.lang.String in the Message because of two
+// issues:
//
// 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded
// strings, but rather fields that were raw bytes incorrectly marked
@@ -160,22 +159,14 @@ int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
// it many cases, the field is never even read by the application code. This
// avoids unnecessary conversions in the common use cases.
//
-// So now, the field for String is maintained as an Object reference which can
-// either store a String or a ByteString. The code uses an instanceof check
-// to see which one it has and converts to the other one if needed. It remembers
-// the last value requested (in a thread safe manner) as this is most likely
-// the one needed next. The thread safety is such that if two threads both
-// convert the field because the changes made by each thread were not visible to
-// the other, they may cause a conversion to happen more times than would
-// otherwise be necessary. This was deemed better than adding synchronization
-// overhead. It will not cause any corruption issues or affect the behavior of
-// the API. The instanceof check is also highly optimized in the JVM and we
-// decided it was better to reduce the memory overhead by not having two
-// separate fields but rather use dynamic type checking.
-//
-// For single fields, the logic for this is done inside the generated code. For
-// repeated fields, the logic is done in LazyStringArrayList and
-// UnmodifiableLazyStringList.
+// In the LITE_RUNTIME, we store strings as java.lang.String because we assume
+// that the users of this runtime are not subject to proto1 constraints and are
+// running code on devices that are user facing. That is, the developers are
+// properly incentivized to only fetch the data they need to read and wish to
+// reduce the number of allocations incurred when running on a user's device.
+
+// TODO(dweis): Consider dropping all of the *Bytes() methods. They really
+// shouldn't be necessary or used on devices.
void ImmutableStringFieldLiteGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
if (SupportFieldPresence(descriptor_->file())) {
@@ -195,7 +186,7 @@ GenerateInterfaceMembers(io::Printer* printer) const {
void ImmutableStringFieldLiteGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private java.lang.Object $name$_;\n");
+ "private java.lang.String $name$_;\n");
PrintExtraFieldInfo(variables_, printer);
if (SupportFieldPresence(descriptor_->file())) {
@@ -209,40 +200,13 @@ GenerateMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public java.lang.String get$capitalized_name$() {\n"
- " java.lang.Object ref = $name$_;\n"
- " if (ref instanceof java.lang.String) {\n"
- " return (java.lang.String) ref;\n"
- " } else {\n"
- " com.google.protobuf.ByteString bs = \n"
- " (com.google.protobuf.ByteString) ref;\n"
- " java.lang.String s = bs.toStringUtf8();\n");
- if (CheckUtf8(descriptor_)) {
- printer->Print(variables_,
- " $name$_ = s;\n");
- } else {
- printer->Print(variables_,
- " if (bs.isValidUtf8()) {\n"
- " $name$_ = s;\n"
- " }\n");
- }
- printer->Print(variables_,
- " return s;\n"
- " }\n"
+ " return $name$_;\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public com.google.protobuf.ByteString\n"
" get$capitalized_name$Bytes() {\n"
- " java.lang.Object ref = $name$_;\n"
- " if (ref instanceof java.lang.String) {\n"
- " com.google.protobuf.ByteString b = \n"
- " com.google.protobuf.ByteString.copyFromUtf8(\n"
- " (java.lang.String) ref);\n"
- " $name$_ = b;\n"
- " return b;\n"
- " } else {\n"
- " return (com.google.protobuf.ByteString) ref;\n"
- " }\n"
+ " return com.google.protobuf.ByteString.copyFromUtf8($name$_);\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
@@ -273,7 +237,7 @@ GenerateMembers(io::Printer* printer) const {
}
printer->Print(variables_,
" $set_has_field_bit_message$\n"
- " $name$_ = value;\n"
+ " $name$_ = value.toStringUtf8();\n"
"}\n");
}
@@ -368,7 +332,7 @@ GenerateParsingCode(io::Printer* printer) const {
"String s = input.readStringRequireUtf8();\n"
"$set_has_field_bit_message$\n"
"$name$_ = s;\n");
- } else if (!HasDescriptorMethods(descriptor_->file())) {
+ } else {
// Lite runtime should attempt to reduce allocations by attempting to
// construct the string directly from the input stream buffer. This avoids
// spurious intermediary ByteString allocations, cutting overall allocations
@@ -377,11 +341,6 @@ GenerateParsingCode(io::Printer* printer) const {
"String s = input.readString();\n"
"$set_has_field_bit_message$\n"
"$name$_ = s;\n");
- } else {
- printer->Print(variables_,
- "com.google.protobuf.ByteString bs = input.readBytes();\n"
- "$set_has_field_bit_message$\n"
- "$name$_ = bs;\n");
}
}
@@ -392,18 +351,24 @@ GenerateParsingDoneCode(io::Printer* printer) const {
void ImmutableStringFieldLiteGenerator::
GenerateSerializationCode(io::Printer* printer) const {
+ // Lite runtime should reduce allocations by serializing the string directly.
+ // This avoids spurious intermediary ByteString allocations, cutting overall
+ // allocations in half.
printer->Print(variables_,
"if ($is_field_present_message$) {\n"
- " output.writeBytes($number$, get$capitalized_name$Bytes());\n"
+ " output.writeString($number$, get$capitalized_name$());\n"
"}\n");
}
void ImmutableStringFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
+ // Lite runtime should reduce allocations by computing on the string directly.
+ // This avoids spurious intermediary ByteString allocations, cutting overall
+ // allocations in half.
printer->Print(variables_,
"if ($is_field_present_message$) {\n"
" size += com.google.protobuf.CodedOutputStream\n"
- " .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
+ " .computeStringSize($number$, get$capitalized_name$());\n"
"}\n");
}
@@ -458,51 +423,22 @@ GenerateMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public java.lang.String get$capitalized_name$() {\n"
- " java.lang.Object ref $default_init$;\n"
+ " java.lang.String ref $default_init$;\n"
" if ($has_oneof_case_message$) {\n"
- " ref = $oneof_name$_;\n"
- " }\n"
- " if (ref instanceof java.lang.String) {\n"
- " return (java.lang.String) ref;\n"
- " } else {\n"
- " com.google.protobuf.ByteString bs = \n"
- " (com.google.protobuf.ByteString) ref;\n"
- " java.lang.String s = bs.toStringUtf8();\n");
- if (CheckUtf8(descriptor_)) {
- printer->Print(variables_,
- " if ($has_oneof_case_message$) {\n"
- " $oneof_name$_ = s;\n"
- " }\n");
- } else {
- printer->Print(variables_,
- " if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n"
- " $oneof_name$_ = s;\n"
- " }\n");
- }
- printer->Print(variables_,
- " return s;\n"
+ " ref = (java.lang.String) $oneof_name$_;\n"
" }\n"
+ " return ref;\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public com.google.protobuf.ByteString\n"
" get$capitalized_name$Bytes() {\n"
- " java.lang.Object ref $default_init$;\n"
+ " java.lang.String ref $default_init$;\n"
" if ($has_oneof_case_message$) {\n"
- " ref = $oneof_name$_;\n"
- " }\n"
- " if (ref instanceof java.lang.String) {\n"
- " com.google.protobuf.ByteString b = \n"
- " com.google.protobuf.ByteString.copyFromUtf8(\n"
- " (java.lang.String) ref);\n"
- " if ($has_oneof_case_message$) {\n"
- " $oneof_name$_ = b;\n"
- " }\n"
- " return b;\n"
- " } else {\n"
- " return (com.google.protobuf.ByteString) ref;\n"
+ " ref = (java.lang.String) $oneof_name$_;\n"
" }\n"
+ " return com.google.protobuf.ByteString.copyFromUtf8(ref);\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
@@ -533,7 +469,7 @@ GenerateMembers(io::Printer* printer) const {
}
printer->Print(variables_,
" $set_oneof_case_message$;\n"
- " $oneof_name$_ = value;\n"
+ " $oneof_name$_ = value.toStringUtf8();\n"
"}\n");
}
@@ -603,7 +539,7 @@ GenerateParsingCode(io::Printer* printer) const {
"String s = input.readStringRequireUtf8();\n"
"$set_oneof_case_message$;\n"
"$oneof_name$_ = s;\n");
- } else if (!HasDescriptorMethods(descriptor_->file())) {
+ } else {
// Lite runtime should attempt to reduce allocations by attempting to
// construct the string directly from the input stream buffer. This avoids
// spurious intermediary ByteString allocations, cutting overall allocations
@@ -612,28 +548,29 @@ GenerateParsingCode(io::Printer* printer) const {
"String s = input.readString();\n"
"$set_oneof_case_message$;\n"
"$oneof_name$_ = s;\n");
- } else {
- printer->Print(variables_,
- "com.google.protobuf.ByteString bs = input.readBytes();\n"
- "$set_oneof_case_message$;\n"
- "$oneof_name$_ = bs;\n");
}
}
void ImmutableStringOneofFieldLiteGenerator::
GenerateSerializationCode(io::Printer* printer) const {
+ // Lite runtime should reduce allocations by serializing the string directly.
+ // This avoids spurious intermediary ByteString allocations, cutting overall
+ // allocations in half.
printer->Print(variables_,
"if ($has_oneof_case_message$) {\n"
- " output.writeBytes($number$, get$capitalized_name$Bytes());\n"
+ " output.writeString($number$, get$capitalized_name$());\n"
"}\n");
}
void ImmutableStringOneofFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
+ // Lite runtime should reduce allocations by computing on the string directly.
+ // This avoids spurious intermediary ByteString allocations, cutting overall
+ // allocations in half.
printer->Print(variables_,
"if ($has_oneof_case_message$) {\n"
" size += com.google.protobuf.CodedOutputStream\n"
- " .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
+ " .computeStringSize($number$, get$capitalized_name$());\n"
"}\n");
}
@@ -667,7 +604,7 @@ void RepeatedImmutableStringFieldLiteGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "$deprecation$com.google.protobuf.ProtocolStringList\n"
+ "$deprecation$java.util.List<String>\n"
" get$capitalized_name$List();\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -685,12 +622,11 @@ GenerateInterfaceMembers(io::Printer* printer) const {
void RepeatedImmutableStringFieldLiteGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private com.google.protobuf.LazyStringArrayList $name$_;\n");
+ "private com.google.protobuf.Internal.ProtobufList<String> $name$_;\n");
PrintExtraFieldInfo(variables_, printer);
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "$deprecation$public com.google.protobuf.ProtocolStringList\n"
- " get$capitalized_name$List() {\n"
+ "$deprecation$public java.util.List<String> get$capitalized_name$List() {\n"
" return $name$_;\n" // note: unmodifiable list
"}\n");
WriteFieldDocComment(printer, descriptor_);
@@ -707,7 +643,8 @@ GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$public com.google.protobuf.ByteString\n"
" get$capitalized_name$Bytes(int index) {\n"
- " return $name$_.getByteString(index);\n"
+ " return com.google.protobuf.ByteString.copyFromUtf8(\n"
+ " $name$_.get(index));\n"
"}\n");
if (descriptor_->options().packed() &&
@@ -719,7 +656,8 @@ GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private void ensure$capitalized_name$IsMutable() {\n"
" if (!$is_mutable$) {\n"
- " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n"
+ " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList(\n"
+ " $name$_);\n"
" }\n"
"}\n");
@@ -764,7 +702,7 @@ GenerateMembers(io::Printer* printer) const {
}
printer->Print(variables_,
" ensure$capitalized_name$IsMutable();\n"
- " $name$_.add(value);\n"
+ " $name$_.add(value.toStringUtf8());\n"
"}\n");
}
@@ -772,10 +710,10 @@ void RepeatedImmutableStringFieldLiteGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "$deprecation$public com.google.protobuf.ProtocolStringList\n"
+ "$deprecation$public java.util.List<String>\n"
" get$capitalized_name$List() {\n"
- " return ((com.google.protobuf.LazyStringList)\n"
- " instance.get$capitalized_name$List()).getUnmodifiableView();\n"
+ " return java.util.Collections.unmodifiableList(\n"
+ " instance.get$capitalized_name$List());\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -875,20 +813,17 @@ GenerateParsingCode(io::Printer* printer) const {
if (CheckUtf8(descriptor_)) {
printer->Print(variables_,
"String s = input.readStringRequireUtf8();\n");
- } else if (!HasDescriptorMethods(descriptor_->file())) {
+ } else {
// Lite runtime should attempt to reduce allocations by attempting to
// construct the string directly from the input stream buffer. This avoids
// spurious intermediary ByteString allocations, cutting overall allocations
// in half.
printer->Print(variables_,
"String s = input.readString();\n");
- } else {
- printer->Print(variables_,
- "com.google.protobuf.ByteString bs = input.readBytes();\n");
}
printer->Print(variables_,
"if (!$is_mutable$) {\n"
- " $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
+ " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList();\n"
"}\n");
if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) {
printer->Print(variables_,
@@ -905,7 +840,7 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const {
"int length = input.readRawVarint32();\n"
"int limit = input.pushLimit(length);\n"
"if (!$is_mutable$ && input.getBytesUntilLimit() > 0) {\n"
- " $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
+ " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList();\n"
"}\n"
"while (input.getBytesUntilLimit() > 0) {\n");
if (CheckUtf8(descriptor_)) {
@@ -932,6 +867,9 @@ GenerateParsingDoneCode(io::Printer* printer) const {
void RepeatedImmutableStringFieldLiteGenerator::
GenerateSerializationCode(io::Printer* printer) const {
+ // Lite runtime should reduce allocations by serializing the string directly.
+ // This avoids spurious intermediary ByteString allocations, cutting overall
+ // allocations in half.
if (descriptor_->options().packed()) {
printer->Print(variables_,
"if (get$capitalized_name$List().size() > 0) {\n"
@@ -939,18 +877,21 @@ GenerateSerializationCode(io::Printer* printer) const {
" output.writeRawVarint32($name$MemoizedSerializedSize);\n"
"}\n"
"for (int i = 0; i < $name$_.size(); i++) {\n"
- " output.write$capitalized_type$NoTag($name$_.get(i));\n"
+ " output.writeStringNoTag($name$_.get(i));\n"
"}\n");
} else {
printer->Print(variables_,
"for (int i = 0; i < $name$_.size(); i++) {\n"
- " output.writeBytes($number$, $name$_.getByteString(i));\n"
+ " output.writeString($number$, $name$_.get(i));\n"
"}\n");
}
}
void RepeatedImmutableStringFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
+ // Lite runtime should reduce allocations by computing on the string directly.
+ // This avoids spurious intermediary ByteString allocations, cutting overall
+ // allocations in half.
printer->Print(variables_,
"{\n"
" int dataSize = 0;\n");
@@ -959,7 +900,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < $name$_.size(); i++) {\n"
" dataSize += com.google.protobuf.CodedOutputStream\n"
- " .computeBytesSizeNoTag($name$_.getByteString(i));\n"
+ " .computeStringSizeNoTag($name$_.get(i));\n"
"}\n");
printer->Print(
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
index 4815a726..584e5a40 100644
--- a/src/google/protobuf/compiler/main.cc
+++ b/src/google/protobuf/compiler/main.cc
@@ -72,7 +72,7 @@ int main(int argc, char* argv[]) {
// CSharp
google::protobuf::compiler::csharp::Generator csharp_generator;
- cli.RegisterGenerator("--csharp_out", &csharp_generator,
+ cli.RegisterGenerator("--csharp_out", "--csharp_opt", &csharp_generator,
"Generate C# source file.");
// Objective C
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index a2eeee2d..4d018425 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -44,6 +44,7 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/map_util.h>
@@ -938,6 +939,42 @@ void Parser::GenerateMapEntry(const MapField& map_field,
} else {
value_field->set_type_name(map_field.value_type_name);
}
+ // Propagate the "enforce_utf8" option to key and value fields if they
+ // are strings. This helps simplify the implementation of code generators
+ // and also reflection-based parsing code.
+ //
+ // The following definition:
+ // message Foo {
+ // map<string, string> value = 1 [enforce_utf8 = false];
+ // }
+ // will be interpreted as:
+ // message Foo {
+ // message ValueEntry {
+ // option map_entry = true;
+ // string key = 1 [enforce_utf8 = false];
+ // string value = 2 [enforce_utf8 = false];
+ // }
+ // repeated ValueEntry value = 1 [enforce_utf8 = false];
+ // }
+ //
+ // TODO(xiaofeng): Remove this when the "enforce_utf8" option is removed
+ // from protocol compiler.
+ for (int i = 0; i < field->options().uninterpreted_option_size(); ++i) {
+ const UninterpretedOption& option =
+ field->options().uninterpreted_option(i);
+ if (option.name_size() == 1 &&
+ option.name(0).name_part() == "enforce_utf8" &&
+ !option.name(0).is_extension()) {
+ if (key_field->type() == FieldDescriptorProto::TYPE_STRING) {
+ key_field->mutable_options()->add_uninterpreted_option()
+ ->CopyFrom(option);
+ }
+ if (value_field->type() == FieldDescriptorProto::TYPE_STRING) {
+ value_field->mutable_options()->add_uninterpreted_option()
+ ->CopyFrom(option);
+ }
+ }
+ }
}
bool Parser::ParseFieldOptions(FieldDescriptorProto* field,
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index 16012e96..007b001c 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -323,7 +323,7 @@ class LIBPROTOBUF_EXPORT Parser {
const LocationRecorder& service_location,
const FileDescriptorProto* containing_file);
- // Parse one statement within a message, enum, or service block, inclunding
+ // Parse one statement within a message, enum, or service block, including
// final semicolon.
bool ParseMessageStatement(DescriptorProto* message,
const LocationRecorder& message_location,
@@ -364,7 +364,7 @@ class LIBPROTOBUF_EXPORT Parser {
const LocationRecorder& extensions_location,
const FileDescriptorProto* containing_file);
- // Parse an "reserved" declaration.
+ // Parse a "reserved" declaration.
bool ParseReserved(DescriptorProto* message,
const LocationRecorder& message_location);
bool ParseReservedNames(DescriptorProto* message,
@@ -415,7 +415,7 @@ class LIBPROTOBUF_EXPORT Parser {
Message* mutable_options);
// Parse "required", "optional", or "repeated" and fill in "label"
- // with the value. Returns true if shuch a label is consumed.
+ // with the value. Returns true if such a label is consumed.
bool ParseLabel(FieldDescriptorProto::Label* label,
const FileDescriptorProto* containing_file);
diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
index cdcaffde..2bebf1f3 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -48,6 +48,7 @@
#include <unistd.h>
#endif
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/plugin.pb.h>
#include <google/protobuf/compiler/code_generator.h>
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index e7890fae..0792d875 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -340,10 +340,10 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorRequest)
// repeated string file_to_generate = 1;
for (int i = 0; i < this->file_to_generate_size(); i++) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
- this->file_to_generate(i).data(), this->file_to_generate(i).length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
- "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->file_to_generate(i).data(), this->file_to_generate(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
::google::protobuf::internal::WireFormatLite::WriteString(
1, this->file_to_generate(i), output);
}
@@ -629,28 +629,28 @@ int CodeGeneratorRequest::proto_file_size() const {
void CodeGeneratorRequest::clear_proto_file() {
proto_file_.Clear();
}
- const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
+const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
return proto_file_.Get(index);
}
- ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
+::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
return proto_file_.Mutable(index);
}
- ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
+::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
// @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
return proto_file_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
-CodeGeneratorRequest::proto_file() const {
- // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
- return proto_file_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
CodeGeneratorRequest::mutable_proto_file() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
return &proto_file_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+CodeGeneratorRequest::proto_file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return proto_file_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -1535,28 +1535,28 @@ int CodeGeneratorResponse::file_size() const {
void CodeGeneratorResponse::clear_file() {
file_.Clear();
}
- const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
+const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file)
return file_.Get(index);
}
- ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) {
+::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file)
return file_.Mutable(index);
}
- ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
+::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
// @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
return file_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
-CodeGeneratorResponse::file() const {
- // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
- return file_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
CodeGeneratorResponse::mutable_file() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file)
return &file_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+CodeGeneratorResponse::file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return file_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index 6fcaea2e..ab79bdae 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -144,10 +144,10 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
const ::google::protobuf::FileDescriptorProto& proto_file(int index) const;
::google::protobuf::FileDescriptorProto* mutable_proto_file(int index);
::google::protobuf::FileDescriptorProto* add_proto_file();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
- proto_file() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
mutable_proto_file();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+ proto_file() const;
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
private:
@@ -378,10 +378,10 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const;
::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index);
::google::protobuf::compiler::CodeGeneratorResponse_File* add_file();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
- file() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
mutable_file();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+ file() const;
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
private:
@@ -534,16 +534,16 @@ inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_
// @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
return proto_file_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
-CodeGeneratorRequest::proto_file() const {
- // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
- return proto_file_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
CodeGeneratorRequest::mutable_proto_file() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
return &proto_file_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+CodeGeneratorRequest::proto_file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return proto_file_;
+}
// -------------------------------------------------------------------
@@ -784,16 +784,16 @@ inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorRe
// @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
return file_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
-CodeGeneratorResponse::file() const {
- // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
- return file_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
CodeGeneratorResponse::mutable_file() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file)
return &file_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+CodeGeneratorResponse::file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return file_;
+}
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
// -------------------------------------------------------------------
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index d4c4c405..e81af700 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -57,6 +57,7 @@
#include <google/protobuf/compiler/python/python_generator.h>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/io/printer.h>
diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
index 2ddac601..aa0f5fce 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -38,6 +38,7 @@
#include <string>
#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/stubs/mutex.h>
#include <google/protobuf/stubs/common.h>
namespace google {
diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc
index a3cff1f8..85429924 100644
--- a/src/google/protobuf/compiler/subprocess.cc
+++ b/src/google/protobuf/compiler/subprocess.cc
@@ -42,6 +42,7 @@
#include <signal.h>
#endif
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/message.h>
#include <google/protobuf/stubs/substitute.h>
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 2855c377..5256b83c 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -53,6 +53,8 @@
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/mutex.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/stubs/strutil.h>
@@ -1092,6 +1094,7 @@ const DescriptorPool* DescriptorPool::generated_pool() {
return generated_pool_;
}
+
DescriptorPool* DescriptorPool::internal_generated_pool() {
InitGeneratedPoolOnce();
return generated_pool_;
@@ -3699,6 +3702,14 @@ static bool ExistingFileMatchesProto(const FileDescriptor* existing_file,
const FileDescriptorProto& proto) {
FileDescriptorProto existing_proto;
existing_file->CopyTo(&existing_proto);
+ // TODO(liujisi): Remove it when CopyTo supports copying syntax params when
+ // syntax="proto2".
+ if (existing_file->syntax() == FileDescriptor::SYNTAX_PROTO2 &&
+ proto.has_syntax()) {
+ existing_proto.set_syntax(
+ existing_file->SyntaxName(existing_file->syntax()));
+ }
+
return existing_proto.SerializeAsString() == proto.SerializeAsString();
}
@@ -4649,7 +4660,7 @@ void DescriptorBuilder::CrossLinkMessage(
// safe.
if (oneof_decl->field_count() > 0 &&
message->field(i - 1)->containing_oneof() != oneof_decl) {
- AddWarning(
+ AddError(
message->full_name() + "." + message->field(i - 1)->name(),
proto.field(i - 1), DescriptorPool::ErrorCollector::OTHER,
strings::Substitute(
@@ -5088,8 +5099,7 @@ void DescriptorBuilder::ValidateProto3Field(
field->containing_type()->full_name() +
"\" which is a proto3 message type.");
}
- bool allow_groups = false;
- if (field->type() == FieldDescriptor::TYPE_GROUP && !allow_groups) {
+ if (field->type() == FieldDescriptor::TYPE_GROUP) {
AddError(field->full_name(), proto,
DescriptorPool::ErrorCollector::TYPE,
"Groups are not supported in proto3 syntax.");
@@ -5307,6 +5317,14 @@ bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field,
// are added.
}
+ if (value->type() == FieldDescriptor::TYPE_ENUM) {
+ if (value->enum_type()->value(0)->number() != 0) {
+ AddError(
+ field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
+ "Enum value in map must define 0 as the first value.");
+ }
+ }
+
return true;
}
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index ca87d634..2ab316a5 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -58,6 +58,7 @@
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
// TYPE_BOOL is defined in the MacOS's ConditionalMacros.h.
#ifdef TYPE_BOOL
@@ -860,7 +861,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptor {
friend class FieldDescriptor;
friend class EnumValueDescriptor;
friend class FileDescriptor;
- friend class LIBPROTOBUF_EXPORT internal::GeneratedMessageReflection;
+ friend class internal::GeneratedMessageReflection;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumDescriptor);
};
@@ -1332,6 +1333,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
// this pool. Do not add your own descriptors to this pool.
static const DescriptorPool* generated_pool();
+
// Find a FileDescriptor in the pool by file name. Returns NULL if not
// found.
const FileDescriptor* FindFileByName(const string& name) const;
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 5e7eeaa7..44f34eeb 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -755,9 +755,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"tion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004s"
"pan\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022"
"\031\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_de"
- "tached_comments\030\006 \003(\tB[\n\023com.google.prot"
+ "tached_comments\030\006 \003(\tBX\n\023com.google.prot"
"obufB\020DescriptorProtosH\001Z\ndescriptor\242\002\003G"
- "PB\252\002\032Google.Protobuf.Reflection\260\002\001", 4994);
+ "PB\252\002\032Google.Protobuf.Reflection", 4991);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -1066,28 +1066,28 @@ int FileDescriptorSet::file_size() const {
void FileDescriptorSet::clear_file() {
file_.Clear();
}
- const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const {
+const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorSet.file)
return file_.Get(index);
}
- ::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) {
+::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorSet.file)
return file_.Mutable(index);
}
- ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() {
+::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() {
// @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file)
return file_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
-FileDescriptorSet::file() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file)
- return file_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
FileDescriptorSet::mutable_file() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file)
return &file_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+FileDescriptorSet::file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file)
+ return file_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -1466,10 +1466,10 @@ void FileDescriptorProto::SerializeWithCachedSizes(
// repeated string dependency = 3;
for (int i = 0; i < this->dependency_size(); i++) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
- this->dependency(i).data(), this->dependency(i).length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
- "google.protobuf.FileDescriptorProto.dependency");
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->dependency(i).data(), this->dependency(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.FileDescriptorProto.dependency");
::google::protobuf::internal::WireFormatLite::WriteString(
3, this->dependency(i), output);
}
@@ -2091,28 +2091,28 @@ int FileDescriptorProto::message_type_size() const {
void FileDescriptorProto::clear_message_type() {
message_type_.Clear();
}
- const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const {
+const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.message_type)
return message_type_.Get(index);
}
- ::google::protobuf::DescriptorProto* FileDescriptorProto::mutable_message_type(int index) {
+::google::protobuf::DescriptorProto* FileDescriptorProto::mutable_message_type(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.message_type)
return message_type_.Mutable(index);
}
- ::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_type() {
+::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_type() {
// @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type)
return message_type_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
-FileDescriptorProto::message_type() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type)
- return message_type_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
FileDescriptorProto::mutable_message_type() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type)
return &message_type_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+FileDescriptorProto::message_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type)
+ return message_type_;
+}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
int FileDescriptorProto::enum_type_size() const {
@@ -2121,28 +2121,28 @@ int FileDescriptorProto::enum_type_size() const {
void FileDescriptorProto::clear_enum_type() {
enum_type_.Clear();
}
- const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const {
+const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.enum_type)
return enum_type_.Get(index);
}
- ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::mutable_enum_type(int index) {
+::google::protobuf::EnumDescriptorProto* FileDescriptorProto::mutable_enum_type(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.enum_type)
return enum_type_.Mutable(index);
}
- ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_type() {
+::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_type() {
// @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type)
return enum_type_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
-FileDescriptorProto::enum_type() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type)
- return enum_type_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
FileDescriptorProto::mutable_enum_type() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type)
return &enum_type_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+FileDescriptorProto::enum_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type)
+ return enum_type_;
+}
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
int FileDescriptorProto::service_size() const {
@@ -2151,28 +2151,28 @@ int FileDescriptorProto::service_size() const {
void FileDescriptorProto::clear_service() {
service_.Clear();
}
- const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const {
+const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.service)
return service_.Get(index);
}
- ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::mutable_service(int index) {
+::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::mutable_service(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.service)
return service_.Mutable(index);
}
- ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_service() {
+::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_service() {
// @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service)
return service_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
-FileDescriptorProto::service() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service)
- return service_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
FileDescriptorProto::mutable_service() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service)
return &service_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+FileDescriptorProto::service() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service)
+ return service_;
+}
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
int FileDescriptorProto::extension_size() const {
@@ -2181,28 +2181,28 @@ int FileDescriptorProto::extension_size() const {
void FileDescriptorProto::clear_extension() {
extension_.Clear();
}
- const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const {
+const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.extension)
return extension_.Get(index);
}
- ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::mutable_extension(int index) {
+::google::protobuf::FieldDescriptorProto* FileDescriptorProto::mutable_extension(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.extension)
return extension_.Mutable(index);
}
- ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extension() {
+::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extension() {
// @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension)
return extension_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
-FileDescriptorProto::extension() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension)
- return extension_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
FileDescriptorProto::mutable_extension() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension)
return &extension_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+FileDescriptorProto::extension() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension)
+ return extension_;
+}
// optional .google.protobuf.FileOptions options = 8;
bool FileDescriptorProto::has_options() const {
@@ -2218,11 +2218,11 @@ void FileDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
clear_has_options();
}
- const ::google::protobuf::FileOptions& FileDescriptorProto::options() const {
+const ::google::protobuf::FileOptions& FileDescriptorProto::options() const {
// @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options)
return options_ != NULL ? *options_ : *default_instance_->options_;
}
- ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() {
+::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() {
set_has_options();
if (options_ == NULL) {
options_ = new ::google::protobuf::FileOptions;
@@ -2230,13 +2230,13 @@ void FileDescriptorProto::clear_options() {
// @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options)
return options_;
}
- ::google::protobuf::FileOptions* FileDescriptorProto::release_options() {
+::google::protobuf::FileOptions* FileDescriptorProto::release_options() {
clear_has_options();
::google::protobuf::FileOptions* temp = options_;
options_ = NULL;
return temp;
}
- void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) {
+void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) {
delete options_;
options_ = options;
if (options) {
@@ -2261,11 +2261,11 @@ void FileDescriptorProto::clear_source_code_info() {
if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
clear_has_source_code_info();
}
- const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const {
+const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const {
// @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info)
return source_code_info_ != NULL ? *source_code_info_ : *default_instance_->source_code_info_;
}
- ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() {
+::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() {
set_has_source_code_info();
if (source_code_info_ == NULL) {
source_code_info_ = new ::google::protobuf::SourceCodeInfo;
@@ -2273,13 +2273,13 @@ void FileDescriptorProto::clear_source_code_info() {
// @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info)
return source_code_info_;
}
- ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() {
+::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() {
clear_has_source_code_info();
::google::protobuf::SourceCodeInfo* temp = source_code_info_;
source_code_info_ = NULL;
return temp;
}
- void FileDescriptorProto::set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info) {
+void FileDescriptorProto::set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info) {
delete source_code_info_;
source_code_info_ = source_code_info;
if (source_code_info) {
@@ -3269,10 +3269,10 @@ void DescriptorProto::SerializeWithCachedSizes(
// repeated string reserved_name = 10;
for (int i = 0; i < this->reserved_name_size(); i++) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
- this->reserved_name(i).data(), this->reserved_name(i).length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
- "google.protobuf.DescriptorProto.reserved_name");
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->reserved_name(i).data(), this->reserved_name(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.DescriptorProto.reserved_name");
::google::protobuf::internal::WireFormatLite::WriteString(
10, this->reserved_name(i), output);
}
@@ -3720,28 +3720,28 @@ int DescriptorProto::field_size() const {
void DescriptorProto::clear_field() {
field_.Clear();
}
- const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const {
+const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.field)
return field_.Get(index);
}
- ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_field(int index) {
+::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_field(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.field)
return field_.Mutable(index);
}
- ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() {
+::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() {
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field)
return field_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
-DescriptorProto::field() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field)
- return field_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
DescriptorProto::mutable_field() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field)
return &field_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::field() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field)
+ return field_;
+}
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
int DescriptorProto::extension_size() const {
@@ -3750,28 +3750,28 @@ int DescriptorProto::extension_size() const {
void DescriptorProto::clear_extension() {
extension_.Clear();
}
- const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const {
+const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension)
return extension_.Get(index);
}
- ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_extension(int index) {
+::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_extension(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension)
return extension_.Mutable(index);
}
- ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension() {
+::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension() {
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension)
return extension_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
-DescriptorProto::extension() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension)
- return extension_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
DescriptorProto::mutable_extension() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension)
return &extension_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::extension() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension)
+ return extension_;
+}
// repeated .google.protobuf.DescriptorProto nested_type = 3;
int DescriptorProto::nested_type_size() const {
@@ -3780,28 +3780,28 @@ int DescriptorProto::nested_type_size() const {
void DescriptorProto::clear_nested_type() {
nested_type_.Clear();
}
- const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const {
+const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.nested_type)
return nested_type_.Get(index);
}
- ::google::protobuf::DescriptorProto* DescriptorProto::mutable_nested_type(int index) {
+::google::protobuf::DescriptorProto* DescriptorProto::mutable_nested_type(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.nested_type)
return nested_type_.Mutable(index);
}
- ::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() {
+::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() {
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type)
return nested_type_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
-DescriptorProto::nested_type() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type)
- return nested_type_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
DescriptorProto::mutable_nested_type() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type)
return &nested_type_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+DescriptorProto::nested_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type)
+ return nested_type_;
+}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
int DescriptorProto::enum_type_size() const {
@@ -3810,28 +3810,28 @@ int DescriptorProto::enum_type_size() const {
void DescriptorProto::clear_enum_type() {
enum_type_.Clear();
}
- const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const {
+const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.enum_type)
return enum_type_.Get(index);
}
- ::google::protobuf::EnumDescriptorProto* DescriptorProto::mutable_enum_type(int index) {
+::google::protobuf::EnumDescriptorProto* DescriptorProto::mutable_enum_type(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.enum_type)
return enum_type_.Mutable(index);
}
- ::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() {
+::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() {
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type)
return enum_type_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
-DescriptorProto::enum_type() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type)
- return enum_type_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
DescriptorProto::mutable_enum_type() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type)
return &enum_type_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+DescriptorProto::enum_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type)
+ return enum_type_;
+}
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
int DescriptorProto::extension_range_size() const {
@@ -3840,28 +3840,28 @@ int DescriptorProto::extension_range_size() const {
void DescriptorProto::clear_extension_range() {
extension_range_.Clear();
}
- const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const {
+const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension_range)
return extension_range_.Get(index);
}
- ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::mutable_extension_range(int index) {
+::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::mutable_extension_range(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension_range)
return extension_range_.Mutable(index);
}
- ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() {
+::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() {
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range)
return extension_range_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
-DescriptorProto::extension_range() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range)
- return extension_range_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
DescriptorProto::mutable_extension_range() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension_range)
return &extension_range_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+DescriptorProto::extension_range() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range)
+ return extension_range_;
+}
// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
int DescriptorProto::oneof_decl_size() const {
@@ -3870,28 +3870,28 @@ int DescriptorProto::oneof_decl_size() const {
void DescriptorProto::clear_oneof_decl() {
oneof_decl_.Clear();
}
- const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const {
+const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.oneof_decl)
return oneof_decl_.Get(index);
}
- ::google::protobuf::OneofDescriptorProto* DescriptorProto::mutable_oneof_decl(int index) {
+::google::protobuf::OneofDescriptorProto* DescriptorProto::mutable_oneof_decl(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.oneof_decl)
return oneof_decl_.Mutable(index);
}
- ::google::protobuf::OneofDescriptorProto* DescriptorProto::add_oneof_decl() {
+::google::protobuf::OneofDescriptorProto* DescriptorProto::add_oneof_decl() {
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl)
return oneof_decl_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
-DescriptorProto::oneof_decl() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl)
- return oneof_decl_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
DescriptorProto::mutable_oneof_decl() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl)
return &oneof_decl_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
+DescriptorProto::oneof_decl() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl)
+ return oneof_decl_;
+}
// optional .google.protobuf.MessageOptions options = 7;
bool DescriptorProto::has_options() const {
@@ -3907,11 +3907,11 @@ void DescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear();
clear_has_options();
}
- const ::google::protobuf::MessageOptions& DescriptorProto::options() const {
+const ::google::protobuf::MessageOptions& DescriptorProto::options() const {
// @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options)
return options_ != NULL ? *options_ : *default_instance_->options_;
}
- ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() {
+::google::protobuf::MessageOptions* DescriptorProto::mutable_options() {
set_has_options();
if (options_ == NULL) {
options_ = new ::google::protobuf::MessageOptions;
@@ -3919,13 +3919,13 @@ void DescriptorProto::clear_options() {
// @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options)
return options_;
}
- ::google::protobuf::MessageOptions* DescriptorProto::release_options() {
+::google::protobuf::MessageOptions* DescriptorProto::release_options() {
clear_has_options();
::google::protobuf::MessageOptions* temp = options_;
options_ = NULL;
return temp;
}
- void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) {
+void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) {
delete options_;
options_ = options;
if (options) {
@@ -3943,28 +3943,28 @@ int DescriptorProto::reserved_range_size() const {
void DescriptorProto::clear_reserved_range() {
reserved_range_.Clear();
}
- const ::google::protobuf::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const {
+const ::google::protobuf::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_range)
return reserved_range_.Get(index);
}
- ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::mutable_reserved_range(int index) {
+::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::mutable_reserved_range(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_range)
return reserved_range_.Mutable(index);
}
- ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() {
+::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() {
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range)
return reserved_range_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
-DescriptorProto::reserved_range() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range)
- return reserved_range_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
DescriptorProto::mutable_reserved_range() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_range)
return &reserved_range_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
+DescriptorProto::reserved_range() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_;
+}
// repeated string reserved_name = 10;
int DescriptorProto::reserved_name_size() const {
@@ -5062,11 +5062,11 @@ void FieldDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
clear_has_options();
}
- const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const {
+const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const {
// @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options)
return options_ != NULL ? *options_ : *default_instance_->options_;
}
- ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() {
+::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() {
set_has_options();
if (options_ == NULL) {
options_ = new ::google::protobuf::FieldOptions;
@@ -5074,13 +5074,13 @@ void FieldDescriptorProto::clear_options() {
// @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options)
return options_;
}
- ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() {
+::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() {
clear_has_options();
::google::protobuf::FieldOptions* temp = options_;
options_ = NULL;
return temp;
}
- void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) {
+void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) {
delete options_;
options_ = options;
if (options) {
@@ -5804,28 +5804,28 @@ int EnumDescriptorProto::value_size() const {
void EnumDescriptorProto::clear_value() {
value_.Clear();
}
- const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const {
+const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.value)
return value_.Get(index);
}
- ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::mutable_value(int index) {
+::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::mutable_value(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.value)
return value_.Mutable(index);
}
- ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_value() {
+::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_value() {
// @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value)
return value_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
-EnumDescriptorProto::value() const {
- // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value)
- return value_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
EnumDescriptorProto::mutable_value() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value)
return &value_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+EnumDescriptorProto::value() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value)
+ return value_;
+}
// optional .google.protobuf.EnumOptions options = 3;
bool EnumDescriptorProto::has_options() const {
@@ -5841,11 +5841,11 @@ void EnumDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear();
clear_has_options();
}
- const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const {
+const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const {
// @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options)
return options_ != NULL ? *options_ : *default_instance_->options_;
}
- ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() {
+::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() {
set_has_options();
if (options_ == NULL) {
options_ = new ::google::protobuf::EnumOptions;
@@ -5853,13 +5853,13 @@ void EnumDescriptorProto::clear_options() {
// @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options)
return options_;
}
- ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() {
+::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() {
clear_has_options();
::google::protobuf::EnumOptions* temp = options_;
options_ = NULL;
return temp;
}
- void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) {
+void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) {
delete options_;
options_ = options;
if (options) {
@@ -6304,11 +6304,11 @@ void EnumValueDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear();
clear_has_options();
}
- const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const {
+const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const {
// @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options)
return options_ != NULL ? *options_ : *default_instance_->options_;
}
- ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() {
+::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() {
set_has_options();
if (options_ == NULL) {
options_ = new ::google::protobuf::EnumValueOptions;
@@ -6316,13 +6316,13 @@ void EnumValueDescriptorProto::clear_options() {
// @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options)
return options_;
}
- ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() {
+::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() {
clear_has_options();
::google::protobuf::EnumValueOptions* temp = options_;
options_ = NULL;
return temp;
}
- void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) {
+void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) {
delete options_;
options_ = options;
if (options) {
@@ -6740,28 +6740,28 @@ int ServiceDescriptorProto::method_size() const {
void ServiceDescriptorProto::clear_method() {
method_.Clear();
}
- const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const {
+const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.method)
return method_.Get(index);
}
- ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::mutable_method(int index) {
+::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::mutable_method(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.method)
return method_.Mutable(index);
}
- ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_method() {
+::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_method() {
// @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method)
return method_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
-ServiceDescriptorProto::method() const {
- // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method)
- return method_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
ServiceDescriptorProto::mutable_method() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method)
return &method_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ServiceDescriptorProto::method() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method)
+ return method_;
+}
// optional .google.protobuf.ServiceOptions options = 3;
bool ServiceDescriptorProto::has_options() const {
@@ -6777,11 +6777,11 @@ void ServiceDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear();
clear_has_options();
}
- const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const {
+const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const {
// @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options)
return options_ != NULL ? *options_ : *default_instance_->options_;
}
- ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() {
+::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() {
set_has_options();
if (options_ == NULL) {
options_ = new ::google::protobuf::ServiceOptions;
@@ -6789,13 +6789,13 @@ void ServiceDescriptorProto::clear_options() {
// @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options)
return options_;
}
- ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() {
+::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() {
clear_has_options();
::google::protobuf::ServiceOptions* temp = options_;
options_ = NULL;
return temp;
}
- void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) {
+void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) {
delete options_;
options_ = options;
if (options) {
@@ -7480,11 +7480,11 @@ void MethodDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear();
clear_has_options();
}
- const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const {
+const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const {
// @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options)
return options_ != NULL ? *options_ : *default_instance_->options_;
}
- ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() {
+::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() {
set_has_options();
if (options_ == NULL) {
options_ = new ::google::protobuf::MethodOptions;
@@ -7492,13 +7492,13 @@ void MethodDescriptorProto::clear_options() {
// @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options)
return options_;
}
- ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() {
+::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() {
clear_has_options();
::google::protobuf::MethodOptions* temp = options_;
options_ = NULL;
return temp;
}
- void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) {
+void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) {
delete options_;
options_ = options;
if (options) {
@@ -9025,28 +9025,28 @@ int FileOptions::uninterpreted_option_size() const {
void FileOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
- const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const {
+const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.FileOptions.uninterpreted_option)
return uninterpreted_option_.Get(index);
}
- ::google::protobuf::UninterpretedOption* FileOptions::mutable_uninterpreted_option(int index) {
+::google::protobuf::UninterpretedOption* FileOptions::mutable_uninterpreted_option(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.uninterpreted_option)
return uninterpreted_option_.Mutable(index);
}
- ::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_option() {
+::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_option() {
// @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-FileOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
FileOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FileOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -9568,28 +9568,28 @@ int MessageOptions::uninterpreted_option_size() const {
void MessageOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
- const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const {
+const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.uninterpreted_option)
return uninterpreted_option_.Get(index);
}
- ::google::protobuf::UninterpretedOption* MessageOptions::mutable_uninterpreted_option(int index) {
+::google::protobuf::UninterpretedOption* MessageOptions::mutable_uninterpreted_option(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.MessageOptions.uninterpreted_option)
return uninterpreted_option_.Mutable(index);
}
- ::google::protobuf::UninterpretedOption* MessageOptions::add_uninterpreted_option() {
+::google::protobuf::UninterpretedOption* MessageOptions::add_uninterpreted_option() {
// @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-MessageOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
MessageOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MessageOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -10298,28 +10298,28 @@ int FieldOptions::uninterpreted_option_size() const {
void FieldOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
- const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const {
+const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.uninterpreted_option)
return uninterpreted_option_.Get(index);
}
- ::google::protobuf::UninterpretedOption* FieldOptions::mutable_uninterpreted_option(int index) {
+::google::protobuf::UninterpretedOption* FieldOptions::mutable_uninterpreted_option(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.uninterpreted_option)
return uninterpreted_option_.Mutable(index);
}
- ::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_option() {
+::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_option() {
// @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-FieldOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
FieldOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FieldOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -10721,28 +10721,28 @@ int EnumOptions::uninterpreted_option_size() const {
void EnumOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
- const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const {
+const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.uninterpreted_option)
return uninterpreted_option_.Get(index);
}
- ::google::protobuf::UninterpretedOption* EnumOptions::mutable_uninterpreted_option(int index) {
+::google::protobuf::UninterpretedOption* EnumOptions::mutable_uninterpreted_option(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.EnumOptions.uninterpreted_option)
return uninterpreted_option_.Mutable(index);
}
- ::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_option() {
+::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_option() {
// @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-EnumOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
EnumOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -11070,28 +11070,28 @@ int EnumValueOptions::uninterpreted_option_size() const {
void EnumValueOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
- const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const {
+const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.uninterpreted_option)
return uninterpreted_option_.Get(index);
}
- ::google::protobuf::UninterpretedOption* EnumValueOptions::mutable_uninterpreted_option(int index) {
+::google::protobuf::UninterpretedOption* EnumValueOptions::mutable_uninterpreted_option(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueOptions.uninterpreted_option)
return uninterpreted_option_.Mutable(index);
}
- ::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() {
+::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() {
// @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-EnumValueOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
EnumValueOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumValueOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -11419,28 +11419,28 @@ int ServiceOptions::uninterpreted_option_size() const {
void ServiceOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
- const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const {
+const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.uninterpreted_option)
return uninterpreted_option_.Get(index);
}
- ::google::protobuf::UninterpretedOption* ServiceOptions::mutable_uninterpreted_option(int index) {
+::google::protobuf::UninterpretedOption* ServiceOptions::mutable_uninterpreted_option(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.ServiceOptions.uninterpreted_option)
return uninterpreted_option_.Mutable(index);
}
- ::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterpreted_option() {
+::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterpreted_option() {
// @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-ServiceOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
ServiceOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ServiceOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -11768,28 +11768,28 @@ int MethodOptions::uninterpreted_option_size() const {
void MethodOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
- const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const {
+const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.uninterpreted_option)
return uninterpreted_option_.Get(index);
}
- ::google::protobuf::UninterpretedOption* MethodOptions::mutable_uninterpreted_option(int index) {
+::google::protobuf::UninterpretedOption* MethodOptions::mutable_uninterpreted_option(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.MethodOptions.uninterpreted_option)
return uninterpreted_option_.Mutable(index);
}
- ::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted_option() {
+::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted_option() {
// @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-MethodOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
MethodOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MethodOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -12710,28 +12710,28 @@ int UninterpretedOption::name_size() const {
void UninterpretedOption::clear_name() {
name_.Clear();
}
- const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const {
+const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.name)
return name_.Get(index);
}
- ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::mutable_name(int index) {
+::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::mutable_name(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.name)
return name_.Mutable(index);
}
- ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::add_name() {
+::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::add_name() {
// @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name)
return name_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
-UninterpretedOption::name() const {
- // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name)
- return name_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
UninterpretedOption::mutable_name() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name)
return &name_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+UninterpretedOption::name() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name)
+ return name_;
+}
// optional string identifier_value = 3;
bool UninterpretedOption::has_identifier_value() const {
@@ -13221,10 +13221,10 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
// repeated string leading_detached_comments = 6;
for (int i = 0; i < this->leading_detached_comments_size(); i++) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
- this->leading_detached_comments(i).data(), this->leading_detached_comments(i).length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
- "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->leading_detached_comments(i).data(), this->leading_detached_comments(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
::google::protobuf::internal::WireFormatLite::WriteString(
6, this->leading_detached_comments(i), output);
}
@@ -13916,28 +13916,28 @@ int SourceCodeInfo::location_size() const {
void SourceCodeInfo::clear_location() {
location_.Clear();
}
- const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const {
+const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.location)
return location_.Get(index);
}
- ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) {
+::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.location)
return location_.Mutable(index);
}
- ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() {
+::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() {
// @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location)
return location_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
-SourceCodeInfo::location() const {
- // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location)
- return location_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
SourceCodeInfo::mutable_location() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location)
return &location_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+SourceCodeInfo::location() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location)
+ return location_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 2aa076ae..931ff02d 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -38,28 +38,28 @@ void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(
void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-class FileDescriptorSet;
-class FileDescriptorProto;
class DescriptorProto;
class DescriptorProto_ExtensionRange;
class DescriptorProto_ReservedRange;
-class FieldDescriptorProto;
-class OneofDescriptorProto;
class EnumDescriptorProto;
+class EnumOptions;
class EnumValueDescriptorProto;
-class ServiceDescriptorProto;
-class MethodDescriptorProto;
+class EnumValueOptions;
+class FieldDescriptorProto;
+class FieldOptions;
+class FileDescriptorProto;
+class FileDescriptorSet;
class FileOptions;
class MessageOptions;
-class FieldOptions;
-class EnumOptions;
-class EnumValueOptions;
-class ServiceOptions;
+class MethodDescriptorProto;
class MethodOptions;
-class UninterpretedOption;
-class UninterpretedOption_NamePart;
+class OneofDescriptorProto;
+class ServiceDescriptorProto;
+class ServiceOptions;
class SourceCodeInfo;
class SourceCodeInfo_Location;
+class UninterpretedOption;
+class UninterpretedOption_NamePart;
enum FieldDescriptorProto_Type {
FieldDescriptorProto_Type_TYPE_DOUBLE = 1,
@@ -249,10 +249,10 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
const ::google::protobuf::FileDescriptorProto& file(int index) const;
::google::protobuf::FileDescriptorProto* mutable_file(int index);
::google::protobuf::FileDescriptorProto* add_file();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
- file() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
mutable_file();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+ file() const;
// @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet)
private:
@@ -405,10 +405,10 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
const ::google::protobuf::DescriptorProto& message_type(int index) const;
::google::protobuf::DescriptorProto* mutable_message_type(int index);
::google::protobuf::DescriptorProto* add_message_type();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
- message_type() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
mutable_message_type();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+ message_type() const;
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
int enum_type_size() const;
@@ -417,10 +417,10 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
::google::protobuf::EnumDescriptorProto* add_enum_type();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
- enum_type() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
mutable_enum_type();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+ enum_type() const;
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
int service_size() const;
@@ -429,10 +429,10 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
const ::google::protobuf::ServiceDescriptorProto& service(int index) const;
::google::protobuf::ServiceDescriptorProto* mutable_service(int index);
::google::protobuf::ServiceDescriptorProto* add_service();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
- service() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
mutable_service();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+ service() const;
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
int extension_size() const;
@@ -441,10 +441,10 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
::google::protobuf::FieldDescriptorProto* add_extension();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
- extension() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
mutable_extension();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ extension() const;
// optional .google.protobuf.FileOptions options = 8;
bool has_options() const;
@@ -797,10 +797,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
const ::google::protobuf::FieldDescriptorProto& field(int index) const;
::google::protobuf::FieldDescriptorProto* mutable_field(int index);
::google::protobuf::FieldDescriptorProto* add_field();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
- field() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
mutable_field();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ field() const;
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
int extension_size() const;
@@ -809,10 +809,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
::google::protobuf::FieldDescriptorProto* add_extension();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
- extension() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
mutable_extension();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ extension() const;
// repeated .google.protobuf.DescriptorProto nested_type = 3;
int nested_type_size() const;
@@ -821,10 +821,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
const ::google::protobuf::DescriptorProto& nested_type(int index) const;
::google::protobuf::DescriptorProto* mutable_nested_type(int index);
::google::protobuf::DescriptorProto* add_nested_type();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
- nested_type() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
mutable_nested_type();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+ nested_type() const;
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
int enum_type_size() const;
@@ -833,10 +833,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
::google::protobuf::EnumDescriptorProto* add_enum_type();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
- enum_type() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
mutable_enum_type();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+ enum_type() const;
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
int extension_range_size() const;
@@ -845,10 +845,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
const ::google::protobuf::DescriptorProto_ExtensionRange& extension_range(int index) const;
::google::protobuf::DescriptorProto_ExtensionRange* mutable_extension_range(int index);
::google::protobuf::DescriptorProto_ExtensionRange* add_extension_range();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
- extension_range() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
mutable_extension_range();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+ extension_range() const;
// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
int oneof_decl_size() const;
@@ -857,10 +857,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
const ::google::protobuf::OneofDescriptorProto& oneof_decl(int index) const;
::google::protobuf::OneofDescriptorProto* mutable_oneof_decl(int index);
::google::protobuf::OneofDescriptorProto* add_oneof_decl();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
- oneof_decl() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
mutable_oneof_decl();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
+ oneof_decl() const;
// optional .google.protobuf.MessageOptions options = 7;
bool has_options() const;
@@ -878,10 +878,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
const ::google::protobuf::DescriptorProto_ReservedRange& reserved_range(int index) const;
::google::protobuf::DescriptorProto_ReservedRange* mutable_reserved_range(int index);
::google::protobuf::DescriptorProto_ReservedRange* add_reserved_range();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
- reserved_range() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
mutable_reserved_range();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
+ reserved_range() const;
// repeated string reserved_name = 10;
int reserved_name_size() const;
@@ -1361,10 +1361,10 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
const ::google::protobuf::EnumValueDescriptorProto& value(int index) const;
::google::protobuf::EnumValueDescriptorProto* mutable_value(int index);
::google::protobuf::EnumValueDescriptorProto* add_value();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
- value() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
mutable_value();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+ value() const;
// optional .google.protobuf.EnumOptions options = 3;
bool has_options() const;
@@ -1596,10 +1596,10 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
const ::google::protobuf::MethodDescriptorProto& method(int index) const;
::google::protobuf::MethodDescriptorProto* mutable_method(int index);
::google::protobuf::MethodDescriptorProto* add_method();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
- method() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
mutable_method();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ method() const;
// optional .google.protobuf.ServiceOptions options = 3;
bool has_options() const;
@@ -2014,10 +2014,10 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
- uninterpreted_option() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.FileOptions)
@@ -2182,10 +2182,10 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
- uninterpreted_option() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions)
@@ -2381,10 +2381,10 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
- uninterpreted_option() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions)
@@ -2508,10 +2508,10 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
- uninterpreted_option() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions)
@@ -2616,10 +2616,10 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
- uninterpreted_option() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions)
@@ -2721,10 +2721,10 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
- uninterpreted_option() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions)
@@ -2826,10 +2826,10 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
- uninterpreted_option() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions)
@@ -3033,10 +3033,10 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
const ::google::protobuf::UninterpretedOption_NamePart& name(int index) const;
::google::protobuf::UninterpretedOption_NamePart* mutable_name(int index);
::google::protobuf::UninterpretedOption_NamePart* add_name();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
- name() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
mutable_name();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+ name() const;
// optional string identifier_value = 3;
bool has_identifier_value() const;
@@ -3356,10 +3356,10 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message {
const ::google::protobuf::SourceCodeInfo_Location& location(int index) const;
::google::protobuf::SourceCodeInfo_Location* mutable_location(int index);
::google::protobuf::SourceCodeInfo_Location* add_location();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
- location() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
mutable_location();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+ location() const;
// @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo)
private:
@@ -3402,16 +3402,16 @@ inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() {
// @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file)
return file_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
-FileDescriptorSet::file() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file)
- return file_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
FileDescriptorSet::mutable_file() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file)
return &file_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+FileDescriptorSet::file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file)
+ return file_;
+}
// -------------------------------------------------------------------
@@ -3656,16 +3656,16 @@ inline ::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_typ
// @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type)
return message_type_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
-FileDescriptorProto::message_type() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type)
- return message_type_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
FileDescriptorProto::mutable_message_type() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type)
return &message_type_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+FileDescriptorProto::message_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type)
+ return message_type_;
+}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
inline int FileDescriptorProto::enum_type_size() const {
@@ -3686,16 +3686,16 @@ inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_ty
// @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type)
return enum_type_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
-FileDescriptorProto::enum_type() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type)
- return enum_type_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
FileDescriptorProto::mutable_enum_type() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type)
return &enum_type_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+FileDescriptorProto::enum_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type)
+ return enum_type_;
+}
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
inline int FileDescriptorProto::service_size() const {
@@ -3716,16 +3716,16 @@ inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_serv
// @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service)
return service_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
-FileDescriptorProto::service() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service)
- return service_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
FileDescriptorProto::mutable_service() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service)
return &service_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+FileDescriptorProto::service() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service)
+ return service_;
+}
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
inline int FileDescriptorProto::extension_size() const {
@@ -3746,16 +3746,16 @@ inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extens
// @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension)
return extension_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
-FileDescriptorProto::extension() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension)
- return extension_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
FileDescriptorProto::mutable_extension() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension)
return &extension_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+FileDescriptorProto::extension() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension)
+ return extension_;
+}
// optional .google.protobuf.FileOptions options = 8;
inline bool FileDescriptorProto::has_options() const {
@@ -4076,16 +4076,16 @@ inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() {
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field)
return field_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
-DescriptorProto::field() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field)
- return field_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
DescriptorProto::mutable_field() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field)
return &field_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::field() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field)
+ return field_;
+}
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
inline int DescriptorProto::extension_size() const {
@@ -4106,16 +4106,16 @@ inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension(
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension)
return extension_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
-DescriptorProto::extension() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension)
- return extension_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
DescriptorProto::mutable_extension() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension)
return &extension_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::extension() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension)
+ return extension_;
+}
// repeated .google.protobuf.DescriptorProto nested_type = 3;
inline int DescriptorProto::nested_type_size() const {
@@ -4136,16 +4136,16 @@ inline ::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() {
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type)
return nested_type_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
-DescriptorProto::nested_type() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type)
- return nested_type_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
DescriptorProto::mutable_nested_type() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type)
return &nested_type_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+DescriptorProto::nested_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type)
+ return nested_type_;
+}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
inline int DescriptorProto::enum_type_size() const {
@@ -4166,16 +4166,16 @@ inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type()
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type)
return enum_type_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
-DescriptorProto::enum_type() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type)
- return enum_type_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
DescriptorProto::mutable_enum_type() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type)
return &enum_type_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+DescriptorProto::enum_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type)
+ return enum_type_;
+}
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
inline int DescriptorProto::extension_range_size() const {
@@ -4196,16 +4196,16 @@ inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range)
return extension_range_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
-DescriptorProto::extension_range() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range)
- return extension_range_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
DescriptorProto::mutable_extension_range() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension_range)
return &extension_range_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+DescriptorProto::extension_range() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range)
+ return extension_range_;
+}
// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
inline int DescriptorProto::oneof_decl_size() const {
@@ -4226,16 +4226,16 @@ inline ::google::protobuf::OneofDescriptorProto* DescriptorProto::add_oneof_decl
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl)
return oneof_decl_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
-DescriptorProto::oneof_decl() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl)
- return oneof_decl_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
DescriptorProto::mutable_oneof_decl() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl)
return &oneof_decl_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
+DescriptorProto::oneof_decl() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl)
+ return oneof_decl_;
+}
// optional .google.protobuf.MessageOptions options = 7;
inline bool DescriptorProto::has_options() const {
@@ -4299,16 +4299,16 @@ inline ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_r
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range)
return reserved_range_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
-DescriptorProto::reserved_range() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range)
- return reserved_range_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
DescriptorProto::mutable_reserved_range() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_range)
return &reserved_range_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
+DescriptorProto::reserved_range() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_;
+}
// repeated string reserved_name = 10;
inline int DescriptorProto::reserved_name_size() const {
@@ -4854,16 +4854,16 @@ inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_va
// @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value)
return value_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
-EnumDescriptorProto::value() const {
- // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value)
- return value_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
EnumDescriptorProto::mutable_value() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value)
return &value_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+EnumDescriptorProto::value() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value)
+ return value_;
+}
// optional .google.protobuf.EnumOptions options = 3;
inline bool EnumDescriptorProto::has_options() const {
@@ -5108,16 +5108,16 @@ inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_me
// @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method)
return method_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
-ServiceDescriptorProto::method() const {
- // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method)
- return method_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
ServiceDescriptorProto::mutable_method() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method)
return &method_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ServiceDescriptorProto::method() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method)
+ return method_;
+}
// optional .google.protobuf.ServiceOptions options = 3;
inline bool ServiceDescriptorProto::has_options() const {
@@ -5945,16 +5945,16 @@ inline ::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_o
// @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-FileOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
FileOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FileOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -6075,16 +6075,16 @@ inline ::google::protobuf::UninterpretedOption* MessageOptions::add_uninterprete
// @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-MessageOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
MessageOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MessageOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -6255,16 +6255,16 @@ inline ::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_
// @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-FieldOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
FieldOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FieldOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -6337,16 +6337,16 @@ inline ::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_o
// @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-EnumOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
EnumOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -6395,16 +6395,16 @@ inline ::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpre
// @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-EnumValueOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
EnumValueOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumValueOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -6453,16 +6453,16 @@ inline ::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterprete
// @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-ServiceOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
ServiceOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ServiceOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -6511,16 +6511,16 @@ inline ::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted
// @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-MethodOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
MethodOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MethodOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -6626,16 +6626,16 @@ inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::ad
// @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name)
return name_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
-UninterpretedOption::name() const {
- // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name)
- return name_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
UninterpretedOption::mutable_name() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name)
return &name_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+UninterpretedOption::name() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name)
+ return name_;
+}
// optional string identifier_value = 3;
inline bool UninterpretedOption::has_identifier_value() const {
@@ -7115,16 +7115,16 @@ inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location
// @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location)
return location_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
-SourceCodeInfo::location() const {
- // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location)
- return location_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
SourceCodeInfo::mutable_location() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location)
return &location_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+SourceCodeInfo::location() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location)
+ return location_;
+}
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
// -------------------------------------------------------------------
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index 9d3dd8fb..bd02ed9b 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -42,7 +42,6 @@ syntax = "proto2";
package google.protobuf;
option go_package = "descriptor";
option java_package = "com.google.protobuf";
-option javanano_use_deprecated_package = true;
option java_outer_classname = "DescriptorProtos";
option csharp_namespace = "Google.Protobuf.Reflection";
option objc_class_prefix = "GPB";
@@ -301,10 +300,12 @@ message FileOptions {
// If set true, then the Java code generator will generate equals() and
// hashCode() methods for all messages defined in the .proto file.
- // - In the full runtime, this is purely a speed optimization, as the
+ // This increases generated code size, potentially substantially for large
+ // protos, which may harm a memory-constrained application.
+ // - In the full runtime this is a speed optimization, as the
// AbstractMessage base class includes reflection-based implementations of
// these methods.
- //- In the lite runtime, setting this option changes the semantics of
+ // - In the lite runtime, setting this option changes the semantics of
// equals() and hashCode() to more closely match those of the full runtime;
// the generated methods compute their results based on field values rather
// than object identity. (Implementations should not assume that hashcodes
@@ -525,6 +526,7 @@ message FieldOptions {
// For Google-internal migration only. Do not use.
optional bool weak = 10 [default=false];
+
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc
index 1c03c443..a87fa049 100644
--- a/src/google/protobuf/descriptor_database_unittest.cc
+++ b/src/google/protobuf/descriptor_database_unittest.cc
@@ -42,7 +42,9 @@
#include <google/protobuf/text_format.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index 760df097..e9b027db 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -49,6 +49,8 @@
#include <google/protobuf/stubs/substitute.h>
#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 <gtest/gtest.h>
@@ -368,6 +370,37 @@ TEST_F(FileDescriptorTest, BuildAgain) {
EXPECT_TRUE(pool_.BuildFile(file) == NULL);
}
+TEST_F(FileDescriptorTest, BuildAgainWithSyntax) {
+ // Test that if te call BuildFile again on the same input we get the same
+ // FileDescriptor back even if syntax param is specified.
+ FileDescriptorProto proto_syntax2;
+ proto_syntax2.set_name("foo_syntax2");
+ proto_syntax2.set_syntax("proto2");
+
+ const FileDescriptor* proto2_descriptor = pool_.BuildFile(proto_syntax2);
+ EXPECT_TRUE(proto2_descriptor != NULL);
+ EXPECT_EQ(proto2_descriptor, pool_.BuildFile(proto_syntax2));
+
+ FileDescriptorProto implicit_proto2;
+ implicit_proto2.set_name("foo_implicit_syntax2");
+
+ const FileDescriptor* implicit_proto2_descriptor =
+ pool_.BuildFile(implicit_proto2);
+ EXPECT_TRUE(implicit_proto2_descriptor != NULL);
+ // We get the same FileDescriptor back if syntax param is explicitly
+ // specified.
+ implicit_proto2.set_syntax("proto2");
+ EXPECT_EQ(implicit_proto2_descriptor, pool_.BuildFile(implicit_proto2));
+
+ FileDescriptorProto proto_syntax3;
+ proto_syntax3.set_name("foo_syntax3");
+ proto_syntax3.set_syntax("proto3");
+
+ const FileDescriptor* proto3_descriptor = pool_.BuildFile(proto_syntax3);
+ EXPECT_TRUE(proto3_descriptor != NULL);
+ EXPECT_EQ(proto3_descriptor, pool_.BuildFile(proto_syntax3));
+}
+
TEST_F(FileDescriptorTest, Syntax) {
FileDescriptorProto proto;
proto.set_name("foo");
@@ -3583,7 +3616,7 @@ TEST_F(ValidationErrorTest, FieldOneofIndexNegative) {
TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) {
// Fields belonging to the same oneof must be defined consecutively.
- BuildFileWithWarnings(
+ BuildFileWithErrors(
"name: \"foo.proto\" "
"message_type {"
" name: \"Foo\""
@@ -3600,7 +3633,7 @@ TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) {
"\"foos\" oneof definition.\n");
// Prevent interleaved fields, which belong to different oneofs.
- BuildFileWithWarnings(
+ BuildFileWithErrors(
"name: \"foo2.proto\" "
"message_type {"
" name: \"Foo2\""
@@ -3621,6 +3654,25 @@ TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) {
"foo2.proto: Foo2.foo2: OTHER: Fields in the same oneof must be defined "
"consecutively. \"foo2\" cannot be defined before the completion of the "
"\"bars\" oneof definition.\n");
+
+ // Another case for normal fields and different oneof fields interleave.
+ BuildFileWithErrors(
+ "name: \"foo3.proto\" "
+ "message_type {"
+ " name: \"Foo3\""
+ " field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 0 }"
+ " field { name:\"bar1\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 1 }"
+ " field { name:\"baz\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ " field { name:\"foo2\" number: 4 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 0 }"
+ " oneof_decl { name:\"foos\" }"
+ " oneof_decl { name:\"bars\" }"
+ "}",
+ "foo3.proto: Foo3.baz: OTHER: Fields in the same oneof must be defined "
+ "consecutively. \"baz\" cannot be defined before the completion of the "
+ "\"foos\" oneof definition.\n");
}
TEST_F(ValidationErrorTest, FieldNumberConflict) {
@@ -5369,6 +5421,35 @@ TEST_F(ValidationErrorTest, MapEntryConflictsWithOneof) {
"with an existing oneof type.\n");
}
+TEST_F(ValidationErrorTest, MapEntryUsesNoneZeroEnumDefaultValue) {
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "enum_type {"
+ " name: \"Bar\""
+ " value { name:\"ENUM_A\" number:1 }"
+ " value { name:\"ENUM_B\" number:2 }"
+ "}"
+ "message_type {"
+ " name: 'Foo' "
+ " field { "
+ " name: 'foo_map' number: 1 label:LABEL_REPEATED "
+ " type_name: 'FooMapEntry' "
+ " } "
+ " nested_type { "
+ " name: 'FooMapEntry' "
+ " options { map_entry: true } "
+ " field { "
+ " name: 'key' number: 1 type:TYPE_INT32 label:LABEL_OPTIONAL "
+ " } "
+ " field { "
+ " name: 'value' number: 2 type_name:\"Bar\" label:LABEL_OPTIONAL "
+ " } "
+ " } "
+ "}",
+ "foo.proto: Foo.foo_map: "
+ "TYPE: Enum value in map must define 0 as the first value.\n");
+}
+
TEST_F(ValidationErrorTest, Proto3RequiredFields) {
BuildFileWithErrors(
"name: 'foo.proto' "
diff --git a/src/google/protobuf/duration.proto b/src/google/protobuf/duration.proto
index 0762c3c2..7f172aa6 100644
--- a/src/google/protobuf/duration.proto
+++ b/src/google/protobuf/duration.proto
@@ -80,6 +80,7 @@ option objc_class_prefix = "GPB";
// }
//
message Duration {
+
// Signed seconds of the span of time. Must be from -315,576,000,000
// to +315,576,000,000 inclusive.
int64 seconds = 1;
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index 318ce6f9..2324d952 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -65,6 +65,7 @@
#include <algorithm>
#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/dynamic_message.h>
@@ -79,6 +80,7 @@
#include <google/protobuf/map_type_handler.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/wire_format.h>
+#include <google/protobuf/map_field.h>
namespace google {
namespace protobuf {
@@ -87,7 +89,7 @@ using internal::WireFormat;
using internal::ExtensionSet;
using internal::GeneratedMessageReflection;
using internal::MapField;
-using internal::MapFieldBase;
+using internal::DynamicMapField;
using internal::ArenaStringPtr;
@@ -116,7 +118,7 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
case FD::CPPTYPE_ENUM : return sizeof(RepeatedField<int >);
case FD::CPPTYPE_MESSAGE:
if (IsMapFieldInApi(field)) {
- return sizeof(MapFieldBase);
+ return sizeof(DynamicMapField);
} else {
return sizeof(RepeatedPtrField<Message>);
}
@@ -389,7 +391,8 @@ void DynamicMessage::SharedCtor() {
new(field_ptr) Message*(NULL);
} else {
if (IsMapFieldInApi(field)) {
- new (field_ptr) MapFieldBase();
+ new (field_ptr) DynamicMapField(
+ type_info_->factory->GetPrototypeNoLock(field->message_type()));
} else {
new (field_ptr) RepeatedPtrField<Message>();
}
@@ -437,8 +440,8 @@ DynamicMessage::~DynamicMessage() {
&(reinterpret_cast<const ArenaStringPtr*>(
type_info_->prototype->OffsetToPointer(
type_info_->offsets[i]))->Get(NULL));
- reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(default_value,
- NULL);
+ reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
+ default_value, NULL);
break;
}
}
@@ -480,7 +483,7 @@ DynamicMessage::~DynamicMessage() {
case FieldDescriptor::CPPTYPE_MESSAGE:
if (IsMapFieldInApi(field)) {
- reinterpret_cast<MapFieldBase*>(field_ptr)->~MapFieldBase();
+ reinterpret_cast<DynamicMapField*>(field_ptr)->~DynamicMapField();
} else {
reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
->~RepeatedPtrField<Message>();
@@ -496,8 +499,8 @@ DynamicMessage::~DynamicMessage() {
&(reinterpret_cast<const ArenaStringPtr*>(
type_info_->prototype->OffsetToPointer(
type_info_->offsets[i]))->Get(NULL));
- reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(default_value,
- NULL);
+ reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
+ default_value, NULL);
break;
}
}
@@ -723,8 +726,14 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
// Allocate the prototype.
void* base = operator new(size);
memset(base, 0, size);
+ // The prototype in type_info has to be set before creating the prototype
+ // instance on memory. e.g., message Foo { map<int32, Foo> a = 1; }. When
+ // creating prototype for Foo, prototype of the map entry will also be
+ // created, which needs the address of the prototype of Foo (the value in
+ // map). To break the cyclic dependency, we have to assgin the address of
+ // prototype into type_info first.
+ type_info->prototype = static_cast<DynamicMessage*>(base);
DynamicMessage* prototype = new(base) DynamicMessage(type_info);
- type_info->prototype = prototype;
// Construct the reflection object.
if (type->oneof_decl_count() > 0) {
diff --git a/src/google/protobuf/dynamic_message.h b/src/google/protobuf/dynamic_message.h
index b5928a52..f74cd7dd 100644
--- a/src/google/protobuf/dynamic_message.h
+++ b/src/google/protobuf/dynamic_message.h
@@ -45,6 +45,7 @@
#include <google/protobuf/message.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/mutex.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/dynamic_message_unittest.cc b/src/google/protobuf/dynamic_message_unittest.cc
index 522a092a..b9796c76 100644
--- a/src/google/protobuf/dynamic_message_unittest.cc
+++ b/src/google/protobuf/dynamic_message_unittest.cc
@@ -40,6 +40,7 @@
// reflection_ops_unittest, cover the rest of the functionality used by
// DynamicMessage.
+#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/descriptor.h>
@@ -48,6 +49,7 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/unittest_no_field_presence.pb.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc
index 1e1c2c8c..50cbd9a8 100644
--- a/src/google/protobuf/empty.pb.cc
+++ b/src/google/protobuf/empty.pb.cc
@@ -79,9 +79,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto() {
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n\033google/protobuf/empty.proto\022\017google.pr"
- "otobuf\"\007\n\005EmptyBJ\n\023com.google.protobufB\n"
- "EmptyProtoP\001\242\002\003GPB\252\002\036Google.Protobuf.Wel"
- "lKnownTypesb\006proto3", 139);
+ "otobuf\"\007\n\005EmptyBM\n\023com.google.protobufB\n"
+ "EmptyProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Protobuf."
+ "WellKnownTypesb\006proto3", 142);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/empty.proto", &protobuf_RegisterTypes);
Empty::default_instance_ = new Empty();
diff --git a/src/google/protobuf/empty.proto b/src/google/protobuf/empty.proto
index 363ec175..9dddc6c5 100644
--- a/src/google/protobuf/empty.proto
+++ b/src/google/protobuf/empty.proto
@@ -34,10 +34,10 @@ package google.protobuf;
option java_multiple_files = true;
option java_outer_classname = "EmptyProto";
option java_package = "com.google.protobuf";
+option java_generate_equals_and_hash = true;
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
option objc_class_prefix = "GPB";
-
// A generic empty message that you can re-use to avoid defining duplicated
// empty messages in your APIs. A typical example is to use it as the request
// or the response type of an API method. For instance:
@@ -46,6 +46,5 @@ option objc_class_prefix = "GPB";
// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
// }
//
-message Empty {
-
-}
+// The JSON representation for `Empty` is empty JSON object `{}`.
+message Empty {}
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index 649ae184..919bd83b 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -34,7 +34,6 @@
#include <google/protobuf/stubs/hash.h>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/once.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/message_lite.h>
#include <google/protobuf/io/coded_stream.h>
@@ -1747,66 +1746,68 @@ void ExtensionSet::Extension::Free() {
// ==================================================================
// Default repeated field instances for iterator-compatible accessors
-const RepeatedStringTypeTraits::RepeatedFieldType*
-RepeatedStringTypeTraits::default_repeated_field_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_primitive_generic_type_traits_once_init_);
+GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_string_type_traits_once_init_);
+GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_message_generic_type_traits_once_init_);
-const RepeatedMessageGenericTypeTraits::RepeatedFieldType*
-RepeatedMessageGenericTypeTraits::default_repeated_field_ = NULL;
+void RepeatedPrimitiveGenericTypeTraits::InitializeDefaultRepeatedFields() {
+ default_repeated_field_int32_ = new RepeatedField<int32>;
+ default_repeated_field_int64_ = new RepeatedField<int64>;
+ default_repeated_field_uint32_ = new RepeatedField<uint32>;
+ default_repeated_field_uint64_ = new RepeatedField<uint64>;
+ default_repeated_field_double_ = new RepeatedField<double>;
+ default_repeated_field_float_ = new RepeatedField<float>;
+ default_repeated_field_bool_ = new RepeatedField<bool>;
+ OnShutdown(&DestroyDefaultRepeatedFields);
+}
+
+void RepeatedPrimitiveGenericTypeTraits::DestroyDefaultRepeatedFields() {
+ delete default_repeated_field_int32_;
+ delete default_repeated_field_int64_;
+ delete default_repeated_field_uint32_;
+ delete default_repeated_field_uint64_;
+ delete default_repeated_field_double_;
+ delete default_repeated_field_float_;
+ delete default_repeated_field_bool_;
+}
-#define PROTOBUF_DEFINE_DEFAULT_REPEATED(TYPE) \
- const RepeatedField<TYPE>* \
- RepeatedPrimitiveGenericTypeTraits::default_repeated_field_##TYPE##_ = NULL;
+void RepeatedStringTypeTraits::InitializeDefaultRepeatedFields() {
+ default_repeated_field_ = new RepeatedFieldType;
+ OnShutdown(&DestroyDefaultRepeatedFields);
+}
-PROTOBUF_DEFINE_DEFAULT_REPEATED(int32)
-PROTOBUF_DEFINE_DEFAULT_REPEATED(int64)
-PROTOBUF_DEFINE_DEFAULT_REPEATED(uint32)
-PROTOBUF_DEFINE_DEFAULT_REPEATED(uint64)
-PROTOBUF_DEFINE_DEFAULT_REPEATED(double)
-PROTOBUF_DEFINE_DEFAULT_REPEATED(float)
-PROTOBUF_DEFINE_DEFAULT_REPEATED(bool)
+void RepeatedStringTypeTraits::DestroyDefaultRepeatedFields() {
+ delete default_repeated_field_;
+}
-#undef PROTOBUF_DEFINE_DEFAULT_REPEATED
+void RepeatedMessageGenericTypeTraits::InitializeDefaultRepeatedFields() {
+ default_repeated_field_ = new RepeatedFieldType;
+ OnShutdown(&DestroyDefaultRepeatedFields);
+}
-struct StaticDefaultRepeatedFieldsInitializer {
- StaticDefaultRepeatedFieldsInitializer() {
- InitializeDefaultRepeatedFields();
- OnShutdown(&DestroyDefaultRepeatedFields);
- }
-} static_repeated_fields_initializer;
-
-void InitializeDefaultRepeatedFields() {
- RepeatedStringTypeTraits::default_repeated_field_ =
- new RepeatedStringTypeTraits::RepeatedFieldType;
- RepeatedMessageGenericTypeTraits::default_repeated_field_ =
- new RepeatedMessageGenericTypeTraits::RepeatedFieldType;
- RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int32_ =
- new RepeatedField<int32>;
- RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int64_ =
- new RepeatedField<int64>;
- RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint32_ =
- new RepeatedField<uint32>;
- RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint64_ =
- new RepeatedField<uint64>;
- RepeatedPrimitiveGenericTypeTraits::default_repeated_field_double_ =
- new RepeatedField<double>;
- RepeatedPrimitiveGenericTypeTraits::default_repeated_field_float_ =
- new RepeatedField<float>;
- RepeatedPrimitiveGenericTypeTraits::default_repeated_field_bool_ =
- new RepeatedField<bool>;
-}
-
-void DestroyDefaultRepeatedFields() {
- delete RepeatedStringTypeTraits::default_repeated_field_;
- delete RepeatedMessageGenericTypeTraits::default_repeated_field_;
- delete RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int32_;
- delete RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int64_;
- delete RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint32_;
- delete RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint64_;
- delete RepeatedPrimitiveGenericTypeTraits::default_repeated_field_double_;
- delete RepeatedPrimitiveGenericTypeTraits::default_repeated_field_float_;
- delete RepeatedPrimitiveGenericTypeTraits::default_repeated_field_bool_;
+void RepeatedMessageGenericTypeTraits::DestroyDefaultRepeatedFields() {
+ delete default_repeated_field_;
}
+const RepeatedField<int32>*
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int32_ = NULL;
+const RepeatedField<int64>*
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int64_ = NULL;
+const RepeatedField<uint32>*
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint32_ = NULL;
+const RepeatedField<uint64>*
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint64_ = NULL;
+const RepeatedField<double>*
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_double_ = NULL;
+const RepeatedField<float>*
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_float_ = NULL;
+const RepeatedField<bool>*
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_bool_ = NULL;
+const RepeatedStringTypeTraits::RepeatedFieldType*
+RepeatedStringTypeTraits::default_repeated_field_ = NULL;
+const RepeatedMessageGenericTypeTraits::RepeatedFieldType*
+RepeatedMessageGenericTypeTraits::default_repeated_field_ = NULL;
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index c371e011..09681259 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -45,6 +45,8 @@
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/once.h>
#include <google/protobuf/repeated_field.h>
@@ -330,6 +332,8 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
const MessageLite& prototype, desc);
MessageLite* AddMessage(const FieldDescriptor* descriptor,
MessageFactory* factory);
+ void AddAllocatedMessage(const FieldDescriptor* descriptor,
+ MessageLite* new_entry);
#undef desc
void RemoveLast(int number);
@@ -578,6 +582,10 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
bool MaybeNewExtension(int number, const FieldDescriptor* descriptor,
Extension** result);
+ // Gets the repeated extension for the given descriptor, creating it if
+ // it does not exist.
+ Extension* MaybeNewRepeatedExtension(const FieldDescriptor* descriptor);
+
// Parse a single MessageSet item -- called just after the item group start
// tag has been read.
bool ParseMessageSetItem(io::CodedInputStream* input,
@@ -716,15 +724,14 @@ class RepeatedPrimitiveTypeTraits {
static const RepeatedFieldType* GetDefaultRepeatedField();
};
-// Declared here so that this can be friended below.
-void InitializeDefaultRepeatedFields();
-void DestroyDefaultRepeatedFields();
+LIBPROTOBUF_EXPORT extern ProtobufOnceType
+repeated_primitive_generic_type_traits_once_init_;
class LIBPROTOBUF_EXPORT RepeatedPrimitiveGenericTypeTraits {
private:
template<typename Type> friend class RepeatedPrimitiveTypeTraits;
- friend void InitializeDefaultRepeatedFields();
- friend void DestroyDefaultRepeatedFields();
+ static void InitializeDefaultRepeatedFields();
+ static void DestroyDefaultRepeatedFields();
static const RepeatedField<int32>* default_repeated_field_int32_;
static const RepeatedField<int64>* default_repeated_field_int64_;
static const RepeatedField<uint32>* default_repeated_field_uint32_;
@@ -759,6 +766,9 @@ template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Add( \
} \
template<> inline const RepeatedField<TYPE>* \
RepeatedPrimitiveTypeTraits<TYPE>::GetDefaultRepeatedField() { \
+ GoogleOnceInit( \
+ &repeated_primitive_generic_type_traits_once_init_, \
+ &RepeatedPrimitiveGenericTypeTraits::InitializeDefaultRepeatedFields); \
return RepeatedPrimitiveGenericTypeTraits:: \
default_repeated_field_##TYPE##_; \
} \
@@ -812,6 +822,9 @@ class LIBPROTOBUF_EXPORT StringTypeTraits {
}
};
+LIBPROTOBUF_EXPORT extern ProtobufOnceType
+repeated_string_type_traits_once_init_;
+
class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
public:
typedef const string& ConstType;
@@ -855,12 +868,14 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
}
static const RepeatedFieldType* GetDefaultRepeatedField() {
+ GoogleOnceInit(&repeated_string_type_traits_once_init_,
+ &InitializeDefaultRepeatedFields);
return default_repeated_field_;
}
private:
- friend void InitializeDefaultRepeatedFields();
- friend void DestroyDefaultRepeatedFields();
+ static void InitializeDefaultRepeatedFields();
+ static void DestroyDefaultRepeatedFields();
static const RepeatedFieldType *default_repeated_field_;
};
@@ -1019,6 +1034,9 @@ class RepeatedMessageTypeTraits {
static const RepeatedFieldType* GetDefaultRepeatedField();
};
+LIBPROTOBUF_EXPORT extern ProtobufOnceType
+repeated_message_generic_type_traits_once_init_;
+
// This class exists only to hold a generic default empty repeated field for all
// message-type repeated field extensions.
class LIBPROTOBUF_EXPORT RepeatedMessageGenericTypeTraits {
@@ -1026,14 +1044,17 @@ class LIBPROTOBUF_EXPORT RepeatedMessageGenericTypeTraits {
typedef RepeatedPtrField< ::google::protobuf::MessageLite*> RepeatedFieldType;
private:
template<typename Type> friend class RepeatedMessageTypeTraits;
- friend void InitializeDefaultRepeatedFields();
- friend void DestroyDefaultRepeatedFields();
+ static void InitializeDefaultRepeatedFields();
+ static void DestroyDefaultRepeatedFields();
static const RepeatedFieldType* default_repeated_field_;
};
template<typename Type> inline
const typename RepeatedMessageTypeTraits<Type>::RepeatedFieldType*
RepeatedMessageTypeTraits<Type>::GetDefaultRepeatedField() {
+ GoogleOnceInit(
+ &repeated_message_generic_type_traits_once_init_,
+ &RepeatedMessageGenericTypeTraits::InitializeDefaultRepeatedFields);
return reinterpret_cast<const RepeatedFieldType*>(
RepeatedMessageGenericTypeTraits::default_repeated_field_);
}
diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc
index 330bd828..82e3e099 100644
--- a/src/google/protobuf/extension_set_heavy.cc
+++ b/src/google/protobuf/extension_set_heavy.cc
@@ -213,8 +213,7 @@ MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
}
}
-MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
- MessageFactory* factory) {
+ExtensionSet::Extension* ExtensionSet::MaybeNewRepeatedExtension(const FieldDescriptor* descriptor) {
Extension* extension;
if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
extension->type = descriptor->type();
@@ -225,6 +224,12 @@ MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
} else {
GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
}
+ return extension;
+}
+
+MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
+ MessageFactory* factory) {
+ Extension* extension = MaybeNewRepeatedExtension(descriptor);
// RepeatedPtrField<Message> does not know how to Add() since it cannot
// allocate an abstract object, so we have to be tricky.
@@ -244,6 +249,13 @@ MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
return result;
}
+void ExtensionSet::AddAllocatedMessage(const FieldDescriptor* descriptor,
+ MessageLite* new_entry) {
+ Extension* extension = MaybeNewRepeatedExtension(descriptor);
+
+ extension->repeated_message_value->AddAllocated(new_entry);
+}
+
static bool ValidateEnumUsingDescriptor(const void* arg, int number) {
return reinterpret_cast<const EnumDescriptor*>(arg)
->FindValueByNumber(number) != NULL;
diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc
index 684ce002..1569120d 100644
--- a/src/google/protobuf/extension_set_unittest.cc
+++ b/src/google/protobuf/extension_set_unittest.cc
@@ -44,6 +44,7 @@
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/testing/googletest.h>
@@ -173,7 +174,7 @@ TEST(ExtensionSetTest, SetAllocatedExtension) {
}
TEST(ExtensionSetTest, ReleaseExtension) {
- unittest::TestMessageSet message;
+ proto2_wireformat_unittest::TestMessageSet message;
EXPECT_FALSE(message.HasExtension(
unittest::TestMessageSetExtension1::message_set_extension));
// Add a extension using SetAllocatedExtension
diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc
index 88020ef2..d8f4ee91 100644
--- a/src/google/protobuf/field_mask.pb.cc
+++ b/src/google/protobuf/field_mask.pb.cc
@@ -81,9 +81,9 @@ void protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto() {
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n google/protobuf/field_mask.proto\022\017goog"
"le.protobuf\"\032\n\tFieldMask\022\r\n\005paths\030\001 \003(\tB"
- "N\n\023com.google.protobufB\016FieldMaskProtoP\001"
- "\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypesb"
- "\006proto3", 167);
+ "Q\n\023com.google.protobufB\016FieldMaskProtoP\001"
+ "\240\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTyp"
+ "esb\006proto3", 170);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/field_mask.proto", &protobuf_RegisterTypes);
FieldMask::default_instance_ = new FieldMask();
@@ -193,11 +193,11 @@ bool FieldMask::MergePartialFromCodedStream(
parse_paths:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->add_paths()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->paths(this->paths_size() - 1).data(),
this->paths(this->paths_size() - 1).length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.FieldMask.paths");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.FieldMask.paths"));
} else {
goto handle_unusual;
}
@@ -232,10 +232,10 @@ void FieldMask::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_start:google.protobuf.FieldMask)
// repeated string paths = 1;
for (int i = 0; i < this->paths_size(); i++) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
- this->paths(i).data(), this->paths(i).length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
- "google.protobuf.FieldMask.paths");
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+ this->paths(i).data(), this->paths(i).length(),
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+ "google.protobuf.FieldMask.paths");
::google::protobuf::internal::WireFormatLite::WriteString(
1, this->paths(i), output);
}
@@ -248,9 +248,9 @@ void FieldMask::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldMask)
// repeated string paths = 1;
for (int i = 0; i < this->paths_size(); i++) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->paths(i).data(), this->paths(i).length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.FieldMask.paths");
target = ::google::protobuf::internal::WireFormatLite::
WriteStringToArray(1, this->paths(i), target);
diff --git a/src/google/protobuf/field_mask.proto b/src/google/protobuf/field_mask.proto
index c19f4410..8b21c692 100644
--- a/src/google/protobuf/field_mask.proto
+++ b/src/google/protobuf/field_mask.proto
@@ -31,13 +31,13 @@ syntax = "proto3";
package google.protobuf;
+option java_generate_equals_and_hash = true;
option java_multiple_files = true;
option java_outer_classname = "FieldMaskProto";
option java_package = "com.google.protobuf";
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
option objc_class_prefix = "GPB";
-
// `FieldMask` represents a set of symbolic field paths, for example:
//
// paths: "f.a"
@@ -52,6 +52,7 @@ option objc_class_prefix = "GPB";
// Field masks also have a custom JSON encoding (see below).
//
// # Field Masks in Projections
+//
// When used in the context of a projection, a response message or
// sub-message is filtered by the API to only contain those fields as
// specified in the mask. For example, if the mask in the previous
@@ -97,6 +98,7 @@ option objc_class_prefix = "GPB";
// behavior for APIs.
//
// # Field Masks in Update Operations
+//
// A field mask in update operations specifies which fields of the
// targeted resource are going to be updated. The API is required
// to only change the values of the fields as specified in the mask
@@ -124,11 +126,13 @@ option objc_class_prefix = "GPB";
// required to be honored by the API.
//
// ## Considerations for HTTP REST
+//
// The HTTP kind of an update operation which uses a field mask must
// be set to PATCH instead of PUT in order to satisfy HTTP semantics
// (PUT must only be used for full updates).
//
// # JSON Encoding of Field Masks
+//
// In JSON, a field mask is encoded as a single string where paths are
// separated by a comma. Fields name in each path are converted
// to/from lower-camel naming conventions.
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index 412c48a1..eee024ee 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -35,6 +35,7 @@
#include <algorithm>
#include <set>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
@@ -57,18 +58,6 @@ bool IsMapFieldInApi(const FieldDescriptor* field) {
}
} // anonymous namespace
-int StringSpaceUsedExcludingSelf(const string& str) {
- const void* start = &str;
- const void* end = &str + 1;
-
- if (start <= str.data() && str.data() < end) {
- // The string's data is stored inside the string object itself.
- return 0;
- } else {
- return str.capacity();
- }
-}
-
bool ParseNamedEnum(const EnumDescriptor* descriptor,
const string& name,
int* value) {
@@ -818,7 +807,16 @@ void GeneratedMessageReflection::ClearField(
}
case FieldDescriptor::CPPTYPE_MESSAGE:
- (*MutableRaw<Message*>(message, field))->Clear();
+ if (has_bits_offset_ == -1) {
+ // Proto3 does not have has-bits and we need to set a message field
+ // to NULL in order to indicate its un-presence.
+ if (GetArena(message) == NULL) {
+ delete *MutableRaw<Message*>(message, field);
+ }
+ *MutableRaw<Message*>(message, field) = NULL;
+ } else {
+ (*MutableRaw<Message*>(message, field))->Clear();
+ }
break;
}
}
@@ -1649,6 +1647,25 @@ Message* GeneratedMessageReflection::AddMessage(
}
}
+void GeneratedMessageReflection::AddAllocatedMessage(
+ Message* message, const FieldDescriptor* field,
+ Message* new_entry) const {
+ USAGE_CHECK_ALL(AddAllocatedMessage, REPEATED, MESSAGE);
+
+ if (field->is_extension()) {
+ MutableExtensionSet(message)->AddAllocatedMessage(field, new_entry);
+ } else {
+ RepeatedPtrFieldBase* repeated = NULL;
+ if (IsMapFieldInApi(field)) {
+ repeated =
+ MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField();
+ } else {
+ repeated = MutableRaw<RepeatedPtrFieldBase>(message, field);
+ }
+ repeated->AddAllocated<GenericTypeHandler<Message> >(new_entry);
+ }
+}
+
void* GeneratedMessageReflection::MutableRawRepeatedField(
Message* message, const FieldDescriptor* field,
FieldDescriptor::CppType cpptype,
@@ -1675,6 +1692,37 @@ void* GeneratedMessageReflection::MutableRawRepeatedField(
}
}
+const void* GeneratedMessageReflection::GetRawRepeatedField(
+ const Message& message, const FieldDescriptor* field,
+ FieldDescriptor::CppType cpptype,
+ int ctype, const Descriptor* desc) const {
+ USAGE_CHECK_REPEATED("GetRawRepeatedField");
+ if (field->cpp_type() != cpptype)
+ ReportReflectionUsageTypeError(descriptor_,
+ field, "GetRawRepeatedField", cpptype);
+ if (ctype >= 0)
+ GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch";
+ if (desc != NULL)
+ GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
+ if (field->is_extension()) {
+ // Should use extension_set::GetRawRepeatedField. However, the required
+ // parameter "default repeated value" is not very easy to get here.
+ // Map is not supported in extensions, it is acceptable to use
+ // extension_set::MutableRawRepeatedField which does not change the message.
+ return MutableExtensionSet(const_cast<Message*>(&message))
+ ->MutableRawRepeatedField(
+ field->number(), field->type(), field->is_packed(), field);
+ } else {
+ // Trigger transform for MapField
+ if (IsMapFieldInApi(field)) {
+ return &(reinterpret_cast<const MapFieldBase*>(
+ reinterpret_cast<const uint8*>(&message) +
+ offsets_[field->index()])->GetRepeatedField());
+ }
+ return reinterpret_cast<const uint8*>(&message) + offsets_[field->index()];
+ }
+}
+
const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor(
const Message& message,
const OneofDescriptor* oneof_descriptor) const {
@@ -1685,6 +1733,69 @@ const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor(
return descriptor_->FindFieldByNumber(field_number);
}
+bool GeneratedMessageReflection::ContainsMapKey(
+ const Message& message,
+ const FieldDescriptor* field,
+ const MapKey& key) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "LookupMapValue",
+ "Field is not a map field.");
+ return GetRaw<MapFieldBase>(message, field).ContainsMapKey(key);
+}
+
+bool GeneratedMessageReflection::InsertOrLookupMapValue(
+ Message* message,
+ const FieldDescriptor* field,
+ const MapKey& key,
+ MapValueRef* val) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "InsertOrLookupMapValue",
+ "Field is not a map field.");
+ val->SetType(field->message_type()->FindFieldByName("value")->cpp_type());
+ return MutableRaw<MapFieldBase>(message, field)->InsertMapValue(key, val);
+}
+
+bool GeneratedMessageReflection::DeleteMapValue(
+ Message* message,
+ const FieldDescriptor* field,
+ const MapKey& key) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "DeleteMapValue",
+ "Field is not a map field.");
+ return MutableRaw<MapFieldBase>(message, field)->DeleteMapValue(key);
+}
+
+MapIterator GeneratedMessageReflection::MapBegin(
+ Message* message,
+ const FieldDescriptor* field) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "MapBegin",
+ "Field is not a map field.");
+ MapIterator iter(message, field);
+ GetRaw<MapFieldBase>(*message, field).MapBegin(&iter);
+ return iter;
+}
+
+MapIterator GeneratedMessageReflection::MapEnd(
+ Message* message,
+ const FieldDescriptor* field) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "MapEnd",
+ "Field is not a map field.");
+ MapIterator iter(message, field);
+ GetRaw<MapFieldBase>(*message, field).MapEnd(&iter);
+ return iter;
+}
+
+int GeneratedMessageReflection::MapSize(
+ const Message& message,
+ const FieldDescriptor* field) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "MapSize",
+ "Field is not a map field.");
+ return GetRaw<MapFieldBase>(message, field).size();
+}
+
// -----------------------------------------------------------------------------
const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName(
@@ -2098,6 +2209,14 @@ void* GeneratedMessageReflection::RepeatedFieldData(
}
}
+MapFieldBase* GeneratedMessageReflection::MapData(
+ Message* message, const FieldDescriptor* field) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "GetMapData",
+ "Field is not a map field.");
+ return MutableRaw<MapFieldBase>(message, field);
+}
+
GeneratedMessageReflection*
GeneratedMessageReflection::NewGeneratedMessageReflection(
const Descriptor* descriptor,
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index dc8abb98..9ef78710 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -58,7 +58,9 @@ class GMR_Handlers;
} // namespace upb
namespace protobuf {
- class DescriptorPool;
+class DescriptorPool;
+class MapKey;
+class MapValueRef;
}
namespace protobuf {
@@ -261,6 +263,25 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
const Message& message,
const OneofDescriptor* oneof_descriptor) const;
+ private:
+ bool ContainsMapKey(const Message& message,
+ const FieldDescriptor* field,
+ const MapKey& key) const;
+ bool InsertOrLookupMapValue(Message* message,
+ const FieldDescriptor* field,
+ const MapKey& key,
+ MapValueRef* val) const;
+ bool DeleteMapValue(Message* message,
+ const FieldDescriptor* field,
+ const MapKey& key) const;
+ MapIterator MapBegin(
+ Message* message,
+ const FieldDescriptor* field) const;
+ MapIterator MapEnd(
+ Message* message,
+ const FieldDescriptor* field) const;
+ int MapSize(const Message& message, const FieldDescriptor* field) const;
+
public:
void SetInt32 (Message* message,
const FieldDescriptor* field, int32 value) const;
@@ -371,6 +392,9 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
int value) const;
Message* AddMessage(Message* message, const FieldDescriptor* field,
MessageFactory* factory = NULL) const;
+ void AddAllocatedMessage(
+ Message* message, const FieldDescriptor* field,
+ Message* new_entry) const;
const FieldDescriptor* FindKnownExtensionByName(const string& name) const;
const FieldDescriptor* FindKnownExtensionByNumber(int number) const;
@@ -391,10 +415,15 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
static const int kUnknownFieldSetInMetadata = -1;
protected:
- virtual void* MutableRawRepeatedField(
+ void* MutableRawRepeatedField(
Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
int ctype, const Descriptor* desc) const;
+ const void* GetRawRepeatedField(
+ const Message& message, const FieldDescriptor* field,
+ FieldDescriptor::CppType, int ctype,
+ const Descriptor* desc) const;
+
virtual MessageFactory* GetMessageFactory() const;
virtual void* RepeatedFieldData(
@@ -407,7 +436,7 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
// To parse directly into a proto2 generated class, the class GMR_Handlers
// needs access to member offsets and hasbits.
- friend class LIBPROTOBUF_EXPORT upb::google_opensource::GMR_Handlers;
+ friend class upb::google_opensource::GMR_Handlers;
const Descriptor* descriptor_;
const Message* default_instance_;
@@ -539,6 +568,9 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
Message* sub_message,
const FieldDescriptor* field) const;
+ internal::MapFieldBase* MapData(
+ Message* message, const FieldDescriptor* field) const;
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratedMessageReflection);
};
diff --git a/src/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc
index ca1a2918..df043844 100644
--- a/src/google/protobuf/generated_message_reflection_unittest.cc
+++ b/src/google/protobuf/generated_message_reflection_unittest.cc
@@ -47,6 +47,7 @@
#include <google/protobuf/test_util.h>
#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
@@ -546,6 +547,57 @@ TEST(GeneratedMessageReflectionTest, SetAllocatedExtensionMessageTest) {
&to_message, TestUtil::ReflectionTester::IS_NULL);
}
+TEST(GeneratedMessageReflectionTest, AddRepeatedMessage) {
+ unittest::TestAllTypes message;
+
+ const Reflection* reflection = message.GetReflection();
+ const Reflection* nested_reflection =
+ unittest::TestAllTypes::NestedMessage::default_instance().GetReflection();
+
+ const FieldDescriptor* nested_bb =
+ unittest::TestAllTypes::NestedMessage::descriptor()->FindFieldByName(
+ "bb");
+
+ Message* nested = reflection->AddMessage(
+ &message, F("repeated_nested_message"));
+ nested_reflection->SetInt32(nested, nested_bb, 11);
+
+ EXPECT_EQ(11, message.repeated_nested_message(0).bb());
+}
+
+TEST(GeneratedMessageReflectionTest, MutableRepeatedMessage) {
+ unittest::TestAllTypes message;
+
+ const Reflection* reflection = message.GetReflection();
+ const Reflection* nested_reflection =
+ unittest::TestAllTypes::NestedMessage::default_instance().GetReflection();
+
+ const FieldDescriptor* nested_bb =
+ unittest::TestAllTypes::NestedMessage::descriptor()->FindFieldByName(
+ "bb");
+
+ message.add_repeated_nested_message()->set_bb(12);
+
+ Message* nested = reflection->MutableRepeatedMessage(
+ &message, F("repeated_nested_message"), 0);
+ EXPECT_EQ(12, nested_reflection->GetInt32(*nested, nested_bb));
+ nested_reflection->SetInt32(nested, nested_bb, 13);
+ EXPECT_EQ(13, message.repeated_nested_message(0).bb());
+}
+
+TEST(GeneratedMessageReflectionTest, AddAllocatedMessage) {
+ unittest::TestAllTypes message;
+
+ const Reflection* reflection = message.GetReflection();
+
+ unittest::TestAllTypes::NestedMessage* nested =
+ new unittest::TestAllTypes::NestedMessage();
+ nested->set_bb(11);
+ reflection->AddAllocatedMessage(&message, F("repeated_nested_message"), nested);
+ EXPECT_EQ(1, message.repeated_nested_message_size());
+ EXPECT_EQ(11, message.repeated_nested_message(0).bb());
+}
+
TEST(GeneratedMessageReflectionTest, ListFieldsOneOf) {
unittest::TestOneof2 message;
TestUtil::SetOneof1(&message);
diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc
index 53cae8b5..afaca2ee 100644
--- a/src/google/protobuf/generated_message_util.cc
+++ b/src/google/protobuf/generated_message_util.cc
@@ -60,6 +60,18 @@ void InitEmptyString() {
OnShutdown(&DeleteEmptyString);
}
+int StringSpaceUsedExcludingSelf(const string& str) {
+ const void* start = &str;
+ const void* end = &str + 1;
+
+ if (start <= str.data() && str.data() < end) {
+ // The string's data is stored inside the string object itself.
+ return 0;
+ } else {
+ return str.capacity();
+ }
+}
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
index 6357e27d..78c8d7ff 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/src/google/protobuf/generated_message_util.h
@@ -89,12 +89,6 @@ LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyString() {
return GetEmptyStringAlreadyInited();
}
-// Defined in generated_message_reflection.cc -- not actually part of the lite
-// library.
-//
-// TODO(jasonh): The various callers get this declaration from a variety of
-// places: probably in most cases repeated_field.h. Clean these up so they all
-// get the declaration from this file.
LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index 3b8650d6..4bcd354f 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -44,6 +44,7 @@
#include <limits.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/arena.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stl_util.h>
@@ -338,9 +339,9 @@ namespace {
// The first part of the pair is true iff the read was successful. The second
// part is buffer + (number of bytes read). This function is always inlined,
// so returning a pair is costless.
-inline ::std::pair<bool, const uint8*> ReadVarint32FromArray(
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE ::std::pair<bool, const uint8*> ReadVarint32FromArray(
uint32 first_byte, const uint8* buffer,
- uint32* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ uint32* value);
inline ::std::pair<bool, const uint8*> ReadVarint32FromArray(
uint32 first_byte, const uint8* buffer, uint32* value) {
// Fast path: We have enough bytes left in the buffer to guarantee that
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index ad351dc3..361c406b 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -191,16 +191,15 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// Like GetDirectBufferPointer, but this method is inlined, and does not
// attempt to Refresh() if the buffer is currently empty.
- inline void GetDirectBufferPointerInline(const void** data,
- int* size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE void GetDirectBufferPointerInline(const void** data,
+ int* size);
// Read raw bytes, copying them into the given buffer.
bool ReadRaw(void* buffer, int size);
// Like the above, with inlined optimizations. This should only be used
// by the protobuf implementation.
- inline bool InternalReadRawInline(void* buffer,
- int size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InternalReadRawInline(void* buffer, int size);
// Like ReadRaw, but reads into a string.
//
@@ -212,8 +211,8 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
bool ReadString(string* buffer, int size);
// Like the above, with inlined optimizations. This should only be used
// by the protobuf implementation.
- inline bool InternalReadStringInline(string* buffer,
- int size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InternalReadStringInline(string* buffer,
+ int size);
// Read a 32-bit little-endian integer.
@@ -243,7 +242,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// Always inline because this is only called in one place per parse loop
// but it is called for every iteration of said loop, so it should be fast.
// GCC doesn't want to inline this by default.
- uint32 ReadTag() GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE uint32 ReadTag();
// This usually a faster alternative to ReadTag() when cutoff is a manifest
// constant. It does particularly well for cutoff >= 127. The first part
@@ -253,8 +252,8 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// above cutoff or is 0. (There's intentional wiggle room when tag is 0,
// because that can arise in several ways, and for best performance we want
// to avoid an extra "is tag == 0?" check here.)
- inline std::pair<uint32, bool> ReadTagWithCutoff(uint32 cutoff)
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE std::pair<uint32, bool> ReadTagWithCutoff(
+ uint32 cutoff);
// Usually returns true if calling ReadVarint32() now would produce the given
// value. Will always return false if ReadVarint32() would not return the
@@ -263,7 +262,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// parameter.
// Always inline because this collapses to a small number of instructions
// when given a constant parameter, but GCC doesn't want to inline by default.
- bool ExpectTag(uint32 expected) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool ExpectTag(uint32 expected);
// Like above, except this reads from the specified buffer. The caller is
// responsible for ensuring that the buffer is large enough to read a varint
@@ -272,9 +271,9 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
//
// Returns a pointer beyond the expected tag if it was found, or NULL if it
// was not.
- static const uint8* ExpectTagFromArray(
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static const uint8* ExpectTagFromArray(
const uint8* buffer,
- uint32 expected) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ uint32 expected);
// Usually returns true if no more bytes can be read. Always returns false
// if more bytes can be read. If ExpectAtEnd() returns true, a subsequent
@@ -766,8 +765,8 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// but GCC by default doesn't want to inline this.
void WriteTag(uint32 value);
// Like WriteTag() but writing directly to the target array.
- static uint8* WriteTagToArray(
- uint32 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static uint8* WriteTagToArray(uint32 value,
+ uint8* target);
// Returns the number of bytes needed to encode the given value as a varint.
static int VarintSize32(uint32 value);
@@ -831,8 +830,8 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// WriteVarint32FallbackToArray. Meanwhile, WriteVarint32() is already
// out-of-line, so it should just invoke this directly to avoid any extra
// function call overhead.
- static uint8* WriteVarint64ToArrayInline(
- uint64 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static uint8* WriteVarint64ToArrayInline(
+ uint64 value, uint8* target);
static int VarintSize32Fallback(uint32 value);
};
diff --git a/src/google/protobuf/io/coded_stream_inl.h b/src/google/protobuf/io/coded_stream_inl.h
index fa20f208..d95b06e0 100644
--- a/src/google/protobuf/io/coded_stream_inl.h
+++ b/src/google/protobuf/io/coded_stream_inl.h
@@ -36,6 +36,7 @@
#ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
#define GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
index 02d5bad3..630c9086 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -41,6 +41,8 @@
#include <limits.h>
#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 <gtest/gtest.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc
index dd7c036e..1be6c863 100644
--- a/src/google/protobuf/io/gzip_stream.cc
+++ b/src/google/protobuf/io/gzip_stream.cc
@@ -33,10 +33,12 @@
// This file contains the implementation of classes GzipInputStream and
// GzipOutputStream.
+
#if HAVE_ZLIB
#include <google/protobuf/io/gzip_stream.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc
index 3ae8c268..7d886506 100644
--- a/src/google/protobuf/io/printer.cc
+++ b/src/google/protobuf/io/printer.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
namespace google {
diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc
index 1331a8d9..258dd986 100644
--- a/src/google/protobuf/io/printer_unittest.cc
+++ b/src/google/protobuf/io/printer_unittest.cc
@@ -37,6 +37,7 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/io/strtod.cc b/src/google/protobuf/io/strtod.cc
index 56973439..579de9aa 100644
--- a/src/google/protobuf/io/strtod.cc
+++ b/src/google/protobuf/io/strtod.cc
@@ -34,6 +34,7 @@
#include <cstring>
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
namespace google {
diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc
index 60bd7957..7ccd633d 100644
--- a/src/google/protobuf/io/tokenizer.cc
+++ b/src/google/protobuf/io/tokenizer.cc
@@ -90,6 +90,7 @@
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/io/strtod.h>
#include <google/protobuf/io/zero_copy_stream.h>
diff --git a/src/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h
index 98576f56..49885eda 100644
--- a/src/google/protobuf/io/tokenizer.h
+++ b/src/google/protobuf/io/tokenizer.h
@@ -40,6 +40,7 @@
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc
index de096fb9..6526056a 100644
--- a/src/google/protobuf/io/tokenizer_unittest.cc
+++ b/src/google/protobuf/io/tokenizer_unittest.cc
@@ -41,6 +41,7 @@
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/testing/googletest.h>
diff --git a/src/google/protobuf/io/zero_copy_stream.cc b/src/google/protobuf/io/zero_copy_stream.cc
index f77c768f..186de001 100644
--- a/src/google/protobuf/io/zero_copy_stream.cc
+++ b/src/google/protobuf/io/zero_copy_stream.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
namespace google {
diff --git a/src/google/protobuf/io/zero_copy_stream_impl.cc b/src/google/protobuf/io/zero_copy_stream_impl.cc
index f7901b27..7ec2b5da 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl.cc
@@ -46,6 +46,7 @@
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/stl_util.h>
diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
index 97b73b88..686e63f2 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
@@ -39,6 +39,7 @@
#include <google/protobuf/stubs/casts.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/stl_util.h>
namespace google {
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 4360b18f..9cdf0378 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
@@ -48,6 +48,7 @@
#include <iosfwd>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/stubs/stl_util.h>
diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc
index f2e5b629..3850e76c 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -46,6 +46,7 @@
// "parametized tests" so that one set of tests can be used on all the
// implementations.
+
#ifdef _MSC_VER
#include <io.h>
#else
@@ -66,6 +67,8 @@
#endif
#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/lite_arena_unittest.cc b/src/google/protobuf/lite_arena_unittest.cc
new file mode 100644
index 00000000..f0bee880
--- /dev/null
+++ b/src/google/protobuf/lite_arena_unittest.cc
@@ -0,0 +1,83 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/arena_test_util.h>
+#include <google/protobuf/map_lite_test_util.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+TEST(LiteArenaTest, MapNoHeapAllocation) {
+ // Allocate a large initial block to avoid mallocs during hooked test.
+ std::vector<char> arena_block(128 * 1024);
+ google::protobuf::ArenaOptions options;
+ options.initial_block = &arena_block[0];
+ options.initial_block_size = arena_block.size();
+ google::protobuf::Arena arena(options);
+ string data;
+ data.reserve(128 * 1024);
+
+ {
+ // TODO(teboring): Enable no heap check when ArenaStringPtr is used in
+ // Map.
+ // google::protobuf::internal::NoHeapChecker no_heap;
+
+ protobuf_unittest::TestArenaMapLite* from =
+ google::protobuf::Arena::CreateMessage<protobuf_unittest::TestArenaMapLite>(&arena);
+ google::protobuf::MapLiteTestUtil::SetArenaMapFields(from);
+ from->SerializeToString(&data);
+
+ protobuf_unittest::TestArenaMapLite* to =
+ google::protobuf::Arena::CreateMessage<protobuf_unittest::TestArenaMapLite>(&arena);
+ to->ParseFromString(data);
+ google::protobuf::MapLiteTestUtil::ExpectArenaMapFieldsSet(*to);
+ }
+}
+
+TEST(LiteArenaTest, UnknownFieldMemLeak) {
+ google::protobuf::Arena arena;
+ protobuf_unittest::ForeignMessageArenaLite* message =
+ google::protobuf::Arena::CreateMessage<protobuf_unittest::ForeignMessageArenaLite>(
+ &arena);
+ string data = "\012\000";
+ int original_capacity = data.capacity();
+ while (data.capacity() <= original_capacity) {
+ data.append("a");
+ }
+ data[1] = data.size() - 2;
+ message->ParseFromString(data);
+}
+
+} // namespace
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc
index 5af8b24d..d1948ab5 100644
--- a/src/google/protobuf/lite_unittest.cc
+++ b/src/google/protobuf/lite_unittest.cc
@@ -33,6 +33,7 @@
#include <string>
#include <iostream>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/arena_test_util.h>
#include <google/protobuf/map_lite_unittest.pb.h>
@@ -377,13 +378,6 @@ int main(int argc, char* argv[]) {
}
{
- // Proto2SetMapFieldsInitialized
- protobuf_unittest::TestEnumStartWithNonZeroMapLite message;
- EXPECT_EQ(protobuf_unittest::PROTO2_NON_ZERO_MAP_ENUM_FOO_LITE,
- (*message.mutable_map_field())[0]);
- }
-
- {
// Clear
protobuf_unittest::TestMapLite message;
@@ -692,37 +686,6 @@ int main(int argc, char* argv[]) {
EXPECT_TRUE(map_message.IsInitialized());
}
- // arena support for map =========================================
-
- {
- // ParsingAndSerializingNoHeapAllocation
-
- // Allocate a large initial block to avoid mallocs during hooked test.
- std::vector<char> arena_block(128 * 1024);
- google::protobuf::ArenaOptions options;
- options.initial_block = &arena_block[0];
- options.initial_block_size = arena_block.size();
- google::protobuf::Arena arena(options);
- string data;
- data.reserve(128 * 1024);
-
- {
- google::protobuf::internal::NoHeapChecker no_heap;
-
- protobuf_unittest::TestArenaMapLite* from =
- google::protobuf::Arena::CreateMessage<protobuf_unittest::TestArenaMapLite>(
- &arena);
- google::protobuf::MapLiteTestUtil::SetArenaMapFields(from);
- from->SerializeToString(&data);
-
- protobuf_unittest::TestArenaMapLite* to =
- google::protobuf::Arena::CreateMessage<protobuf_unittest::TestArenaMapLite>(
- &arena);
- to->ParseFromString(data);
- google::protobuf::MapLiteTestUtil::ExpectArenaMapFieldsSet(*to);
- }
- }
-
std::cout << "PASS" << std::endl;
return 0;
}
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index d928b7a7..8b61573d 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -35,9 +35,12 @@
#include <google/protobuf/stubs/hash.h>
#include <limits> // To support Visual Studio 2008
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/arena.h>
#include <google/protobuf/generated_enum_util.h>
#include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/descriptor.h>
namespace google {
namespace protobuf {
@@ -47,13 +50,379 @@ class Map;
template <typename Enum> struct is_proto_enum;
+class MapIterator;
+
namespace internal {
template <typename Key, typename T,
WireFormatLite::FieldType key_wire_type,
WireFormatLite::FieldType value_wire_type,
int default_enum_value>
class MapFieldLite;
-}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+class MapField;
+
+template <typename Key, typename T>
+class TypeDefinedMapFieldBase;
+
+class DynamicMapField;
+
+class GeneratedMessageReflection;
+} // namespace internal
+
+#define TYPE_CHECK(EXPECTEDTYPE, METHOD) \
+ if (type() != EXPECTEDTYPE) { \
+ GOOGLE_LOG(FATAL) \
+ << "Protocol Buffer map usage error:\n" \
+ << METHOD << " type does not match\n" \
+ << " Expected : " \
+ << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \
+ << " Actual : " \
+ << FieldDescriptor::CppTypeName(type()); \
+ }
+
+// MapKey is an union type for representing any possible
+// map key.
+class LIBPROTOBUF_EXPORT MapKey {
+ public:
+ MapKey() : type_(0) {
+ }
+ MapKey(const MapKey& other) : type_(0) {
+ CopyFrom(other);
+ }
+
+ ~MapKey() {
+ if (type_ == FieldDescriptor::CPPTYPE_STRING) {
+ delete val_.string_value_;
+ }
+ }
+
+ FieldDescriptor::CppType type() const {
+ if (type_ == 0) {
+ GOOGLE_LOG(FATAL)
+ << "Protocol Buffer map usage error:\n"
+ << "MapKey::type MapKey is not initialized. "
+ << "Call set methods to initialize MapKey.";
+ }
+ return (FieldDescriptor::CppType)type_;
+ }
+
+ void SetInt64Value(int64 value) {
+ SetType(FieldDescriptor::CPPTYPE_INT64);
+ val_.int64_value_ = value;
+ }
+ void SetUInt64Value(uint64 value) {
+ SetType(FieldDescriptor::CPPTYPE_UINT64);
+ val_.uint64_value_ = value;
+ }
+ void SetInt32Value(int32 value) {
+ SetType(FieldDescriptor::CPPTYPE_INT32);
+ val_.int32_value_ = value;
+ }
+ void SetUInt32Value(uint32 value) {
+ SetType(FieldDescriptor::CPPTYPE_UINT32);
+ val_.uint32_value_ = value;
+ }
+ void SetBoolValue(bool value) {
+ SetType(FieldDescriptor::CPPTYPE_BOOL);
+ val_.bool_value_ = value;
+ }
+ void SetStringValue(const string& val) {
+ SetType(FieldDescriptor::CPPTYPE_STRING);
+ *val_.string_value_ = val;
+ }
+
+ int64 GetInt64Value() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
+ "MapKey::GetInt64Value");
+ return val_.int64_value_;
+ }
+ uint64 GetUInt64Value() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
+ "MapKey::GetUInt64Value");
+ return val_.uint64_value_;
+ }
+ int32 GetInt32Value() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
+ "MapKey::GetInt32Value");
+ return val_.int32_value_;
+ }
+ uint32 GetUInt32Value() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
+ "MapKey::GetUInt32Value");
+ return val_.uint32_value_;
+ }
+ int32 GetBoolValue() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL,
+ "MapKey::GetBoolValue");
+ return val_.bool_value_;
+ }
+ const string& GetStringValue() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
+ "MapKey::GetStringValue");
+ return *val_.string_value_;
+ }
+
+ bool operator==(const MapKey& other) const {
+ if (type_ != other.type_) {
+ return false;
+ }
+ switch (type()) {
+ case FieldDescriptor::CPPTYPE_STRING:
+ return *val_.string_value_ == *other.val_.string_value_;
+ case FieldDescriptor::CPPTYPE_INT64:
+ return val_.int64_value_ == other.val_.int64_value_;
+ case FieldDescriptor::CPPTYPE_INT32:
+ return val_.int32_value_ == other.val_.int32_value_;
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return val_.uint64_value_ == other.val_.uint64_value_;
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return val_.uint32_value_ == other.val_.uint32_value_;
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return val_.bool_value_ == other.val_.bool_value_;
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ case FieldDescriptor::CPPTYPE_ENUM:
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return false;
+ }
+ }
+
+ void CopyFrom(const MapKey& other) {
+ SetType(other.type());
+ switch (type_) {
+ case FieldDescriptor::CPPTYPE_STRING:
+ *val_.string_value_ = *other.val_.string_value_;
+ break;
+ case FieldDescriptor::CPPTYPE_INT64:
+ val_.int64_value_ = other.val_.int64_value_;
+ break;
+ case FieldDescriptor::CPPTYPE_INT32:
+ val_.int32_value_ = other.val_.int32_value_;
+ break;
+ case FieldDescriptor::CPPTYPE_UINT64:
+ val_.uint64_value_ = other.val_.uint64_value_;
+ break;
+ case FieldDescriptor::CPPTYPE_UINT32:
+ val_.uint32_value_ = other.val_.uint32_value_;
+ break;
+ case FieldDescriptor::CPPTYPE_BOOL:
+ val_.bool_value_ = other.val_.bool_value_;
+ break;
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ case FieldDescriptor::CPPTYPE_ENUM:
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ break;
+ }
+ }
+
+ private:
+ template <typename K, typename V>
+ friend class internal::TypeDefinedMapFieldBase;
+ friend class MapIterator;
+ friend class internal::DynamicMapField;
+
+ union KeyValue {
+ KeyValue() {}
+ string* string_value_;
+ int64 int64_value_;
+ int32 int32_value_;
+ uint64 uint64_value_;
+ uint32 uint32_value_;
+ bool bool_value_;
+ } val_;
+
+ void SetType(FieldDescriptor::CppType type) {
+ if (type_ == type) return;
+ if (type_ == FieldDescriptor::CPPTYPE_STRING) {
+ delete val_.string_value_;
+ }
+ type_ = type;
+ if (type_ == FieldDescriptor::CPPTYPE_STRING) {
+ val_.string_value_ = new string;
+ }
+ }
+
+ // type_ is 0 or a valid FieldDescriptor::CppType.
+ int type_;
+};
+
+// MapValueRef points to a map value.
+class LIBPROTOBUF_EXPORT MapValueRef {
+ public:
+ MapValueRef() : data_(NULL), type_(0) {}
+
+ void SetInt64Value(int64 value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
+ "MapValueRef::SetInt64Value");
+ *reinterpret_cast<int64*>(data_) = value;
+ }
+ void SetUInt64Value(uint64 value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
+ "MapValueRef::SetUInt64Value");
+ *reinterpret_cast<uint64*>(data_) = value;
+ }
+ void SetInt32Value(int32 value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
+ "MapValueRef::SetInt32Value");
+ *reinterpret_cast<int32*>(data_) = value;
+ }
+ void SetUInt32Value(uint64 value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
+ "MapValueRef::SetUInt32Value");
+ *reinterpret_cast<uint32*>(data_) = value;
+ }
+ void SetBoolValue(bool value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL,
+ "MapValueRef::SetBoolValue");
+ *reinterpret_cast<bool*>(data_) = value;
+ }
+ // TODO(jieluo) - Checks that enum is member.
+ void SetEnumValue(int value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM,
+ "MapValueRef::SetEnumValue");
+ *reinterpret_cast<int*>(data_) = value;
+ }
+ void SetStringValue(const string& value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
+ "MapValueRef::SetStringValue");
+ *reinterpret_cast<string*>(data_) = value;
+ }
+ void SetFloatValue(float value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT,
+ "MapValueRef::SetFloatValue");
+ *reinterpret_cast<float*>(data_) = value;
+ }
+ void SetDoubleValue(double value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE,
+ "MapValueRef::SetDoubleValue");
+ *reinterpret_cast<double*>(data_) = value;
+ }
+
+ int64 GetInt64Value() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
+ "MapValueRef::GetInt64Value");
+ return *reinterpret_cast<int64*>(data_);
+ }
+ uint64 GetUInt64Value() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
+ "MapValueRef::GetUInt64Value");
+ return *reinterpret_cast<uint64*>(data_);
+ }
+ int32 GetInt32Value() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
+ "MapValueRef::GetInt32Value");
+ return *reinterpret_cast<int32*>(data_);
+ }
+ uint32 GetUInt32Value() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
+ "MapValueRef::GetUInt32Value");
+ return *reinterpret_cast<uint32*>(data_);
+ }
+ bool GetBoolValue() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL,
+ "MapValueRef::GetBoolValue");
+ return *reinterpret_cast<bool*>(data_);
+ }
+ int GetEnumValue() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM,
+ "MapValueRef::GetEnumValue");
+ return *reinterpret_cast<int*>(data_);
+ }
+ const string& GetStringValue() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
+ "MapValueRef::GetStringValue");
+ return *reinterpret_cast<string*>(data_);
+ }
+ float GetFloatValue() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT,
+ "MapValueRef::GetFloatValue");
+ return *reinterpret_cast<float*>(data_);
+ }
+ double GetDoubleValue() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE,
+ "MapValueRef::GetDoubleValue");
+ return *reinterpret_cast<double*>(data_);
+ }
+
+ const Message& GetMessageValue() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
+ "MapValueRef::GetMessageValue");
+ return *reinterpret_cast<Message*>(data_);
+ }
+
+ Message* MutableMessageValue() {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
+ "MapValueRef::MutableMessageValue");
+ return reinterpret_cast<Message*>(data_);
+ }
+
+ private:
+ template <typename K, typename V,
+ internal::WireFormatLite::FieldType key_wire_type,
+ internal::WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+ friend class internal::MapField;
+ template <typename K, typename V>
+ friend class internal::TypeDefinedMapFieldBase;
+ friend class MapIterator;
+ friend class internal::GeneratedMessageReflection;
+ friend class internal::DynamicMapField;
+
+ void SetType(FieldDescriptor::CppType type) {
+ type_ = type;
+ }
+
+ FieldDescriptor::CppType type() const {
+ if (type_ == 0 || data_ == NULL) {
+ GOOGLE_LOG(FATAL)
+ << "Protocol Buffer map usage error:\n"
+ << "MapValueRef::type MapValueRef is not initialized.";
+ }
+ return (FieldDescriptor::CppType)type_;
+ }
+ void SetValue(const void* val) {
+ data_ = const_cast<void*>(val);
+ }
+ void CopyFrom(const MapValueRef& other) {
+ type_ = other.type_;
+ data_ = other.data_;
+ }
+ // Only used in DynamicMapField
+ void DeleteData() {
+ switch (type_) {
+#define HANDLE_TYPE(CPPTYPE, TYPE) \
+ case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \
+ delete reinterpret_cast<TYPE*>(data_); \
+ break; \
+ }
+ HANDLE_TYPE(INT32, int32);
+ HANDLE_TYPE(INT64, int64);
+ HANDLE_TYPE(UINT32, uint32);
+ HANDLE_TYPE(UINT64, uint64);
+ HANDLE_TYPE(DOUBLE, double);
+ HANDLE_TYPE(FLOAT, float);
+ HANDLE_TYPE(BOOL, bool);
+ HANDLE_TYPE(STRING, string);
+ HANDLE_TYPE(ENUM, int32);
+ HANDLE_TYPE(MESSAGE, Message);
+#undef HANDLE_TYPE
+ }
+ }
+ // data_ point to a map value. MapValueRef does not
+ // own this value.
+ void* data_;
+ // type_ is 0 or a valid FieldDescriptor::CppType.
+ int type_;
+};
+
+#undef TYPE_CHECK
// This is the class for google::protobuf::Map's internal value_type. Instead of using
// std::pair as value_type, we use this class which provides us more control of
@@ -82,7 +451,6 @@ class MapPair {
T second;
private:
- typedef void DestructorSkippable_;
friend class ::google::protobuf::Arena;
friend class Map<Key, T>;
};
@@ -92,9 +460,6 @@ class MapPair {
// interface directly to visit or change map fields.
template <typename Key, typename T>
class Map {
- typedef internal::MapCppTypeHandler<Key> KeyTypeHandler;
- typedef internal::MapCppTypeHandler<T> ValueTypeHandler;
-
public:
typedef Key key_type;
typedef T mapped_type;
@@ -118,7 +483,9 @@ class Map {
: arena_(arena),
allocator_(arena_),
elements_(0, hasher(), key_equal(), allocator_),
- default_enum_value_(0) {}
+ default_enum_value_(0) {
+ arena_->OwnDestructor(&elements_);
+ }
Map(const Map& other)
: arena_(NULL),
@@ -127,6 +494,14 @@ class Map {
default_enum_value_(other.default_enum_value_) {
insert(other.begin(), other.end());
}
+ template <class InputIt>
+ explicit Map(const InputIt& first, const InputIt& last)
+ : arena_(NULL),
+ allocator_(arena_),
+ elements_(0, hasher(), key_equal(), allocator_),
+ default_enum_value_(0) {
+ insert(first, last);
+ }
~Map() { clear(); }
@@ -172,7 +547,7 @@ class Map {
!defined(GOOGLE_PROTOBUF_OS_NACL) && !defined(GOOGLE_PROTOBUF_OS_ANDROID)
template<class NodeType, class... Args>
void construct(NodeType* p, Args&&... args) {
- new ((void*)p) NodeType(std::forward<Args>(args)...);
+ new (static_cast<void*>(p)) NodeType(std::forward<Args>(args)...);
}
template<class NodeType>
@@ -206,6 +581,7 @@ class Map {
}
private:
+ typedef void DestructorSkippable_;
Arena* arena_;
template <typename X>
@@ -449,6 +825,58 @@ class Map {
};
} // namespace protobuf
-
} // namespace google
+
+GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START
+template<>
+struct hash<google::protobuf::MapKey> {
+ size_t
+ operator()(const google::protobuf::MapKey& map_key) const {
+ switch (map_key.type()) {
+ case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
+ return hash<string>()(map_key.GetStringValue());
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
+ return hash< ::google::protobuf::int64>()(map_key.GetInt64Value());
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
+ return hash< ::google::protobuf::int32>()(map_key.GetInt32Value());
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
+ return hash< ::google::protobuf::uint64>()(map_key.GetUInt64Value());
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
+ return hash< ::google::protobuf::uint32>()(map_key.GetUInt32Value());
+ case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
+ return hash<bool>()(map_key.GetBoolValue());
+ case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
+ case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
+ case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return 0;
+ }
+ }
+ bool
+ operator()(const google::protobuf::MapKey& map_key1,
+ const google::protobuf::MapKey& map_key2) const {
+ switch (map_key1.type()) {
+#define COMPARE_CPPTYPE(CPPTYPE, CPPTYPE_METHOD) \
+ case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: \
+ return map_key1.Get##CPPTYPE_METHOD##Value() < \
+ map_key2.Get##CPPTYPE_METHOD##Value();
+ COMPARE_CPPTYPE(STRING, String)
+ COMPARE_CPPTYPE(INT64, Int64)
+ COMPARE_CPPTYPE(INT32, Int32)
+ COMPARE_CPPTYPE(UINT64, UInt64)
+ COMPARE_CPPTYPE(UINT32, UInt32)
+ COMPARE_CPPTYPE(BOOL, Bool)
+#undef COMPARE_CPPTYPE
+ case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
+ case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
+ case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return true;
+ }
+ }
+};
+GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
+
#endif // GOOGLE_PROTOBUF_MAP_H__
diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h
index e93d0348..987c4e29 100644
--- a/src/google/protobuf/map_entry.h
+++ b/src/google/protobuf/map_entry.h
@@ -34,6 +34,7 @@
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/map_entry_lite.h>
#include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/metadata.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/wire_format_lite_inl.h>
@@ -79,40 +80,46 @@ class LIBPROTOBUF_EXPORT MapEntryBase : public Message {
// MapEntry is the returned google::protobuf::Message when calling AddMessage of
// google::protobuf::Reflection. In order to let it work with generated message
-// reflection, its internal layout is the same as generated message with the
-// same fields. However, in order to decide the internal layout of key/value, we
-// need to know both their cpp type in generated api and proto type.
+// reflection, its in-memory type is the same as generated message with the same
+// fields. However, in order to decide the in-memory type of key/value, we need
+// to know both their cpp type in generated api and proto type. In
+// implmentation, all in-memory types have related wire format functions to
+// support except ArenaStringPtr. Therefore, we need to define another type with
+// supporting wire format functions. Since this type is only used as return type
+// of MapEntry accessors, it's named MapEntry accessor type.
//
-// cpp type | proto type | internal layout
-// int32 TYPE_INT32 int32
-// int32 TYPE_FIXED32 int32
-// FooEnum TYPE_ENUM int
-// FooMessage TYPE_MESSAGE FooMessage*
+// cpp type: the type visible to users in public API.
+// proto type: WireFormatLite::FieldType of the field.
+// in-memory type: type of the data member used to stored this field.
+// MapEntry accessor type: type used in MapEntry getters/mutators to access the
+// field.
//
-// The internal layouts of primitive types can be inferred from its proto type,
-// while we need to explicitly tell cpp type if proto type is TYPE_MESSAGE to
-// get internal layout.
-// Moreover, default_enum_value is used to initialize enum field in proto2.
+// cpp type | proto type | in-memory type | MapEntry accessor type
+// int32 TYPE_INT32 int32 int32
+// int32 TYPE_FIXED32 int32 int32
+// string TYPE_STRING ArenaStringPtr string
+// FooEnum TYPE_ENUM int int
+// FooMessage TYPE_MESSAGE FooMessage* FooMessage
+//
+// The in-memory types of primitive types can be inferred from its proto type,
+// while we need to explicitly specify the cpp type if proto type is
+// TYPE_MESSAGE to infer the in-memory type. Moreover, default_enum_value is
+// used to initialize enum field in proto2.
template <typename Key, typename Value,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType,
int default_enum_value>
class MapEntry : public MapEntryBase {
- // Handlers for key/value wire type. Provide utilities to parse/serialize
- // key/value.
- typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler;
- typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler;
-
- // Define key/value's internal stored type. Message is the only one whose
- // internal stored type cannot be inferred from its proto type.
- static const bool kIsKeyMessage = KeyWireHandler::kIsMessage;
- static const bool kIsValueMessage = ValueWireHandler::kIsMessage;
- typedef typename KeyWireHandler::CppType KeyInternalType;
- typedef typename ValueWireHandler::CppType ValueInternalType;
- typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type
- KeyCppType;
- typedef typename MapIf<kIsValueMessage, Value, ValueInternalType>::type
- ValCppType;
+ // Provide utilities to parse/serialize key/value. Provide utilities to
+ // manipulate internal stored type.
+ typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
+ typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
+
+ // Enum type cannot be used for MapTypeHandler::Read. Define a type
+ // which will replace Enum with int.
+ typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType;
+ typedef typename ValueTypeHandler::MapEntryAccessorType
+ ValueMapEntryAccessorType;
// Abbreviation for MapEntry
typedef typename google::protobuf::internal::MapEntry<
@@ -132,16 +139,16 @@ class MapEntry : public MapEntryBase {
// accessors ======================================================
- virtual inline const KeyCppType& key() const {
+ virtual inline const KeyMapEntryAccessorType& key() const {
return entry_lite_.key();
}
- inline KeyCppType* mutable_key() {
+ inline KeyMapEntryAccessorType* mutable_key() {
return entry_lite_.mutable_key();
}
- virtual inline const ValCppType& value() const {
+ virtual inline const ValueMapEntryAccessorType& value() const {
return entry_lite_.value();
}
- inline ValCppType* mutable_value() {
+ inline ValueMapEntryAccessorType* mutable_value() {
return entry_lite_.mutable_value();
}
@@ -240,7 +247,9 @@ class MapEntry : public MapEntryBase {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_._has_bits_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _unknown_fields_), -1,
DescriptorPool::generated_pool(),
- ::google::protobuf::MessageFactory::generated_factory(), sizeof(MapEntry), -1);
+ ::google::protobuf::MessageFactory::generated_factory(),
+ sizeof(MapEntry),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _internal_metadata_));
entry->descriptor_ = descriptor;
entry->reflection_ = reflection;
entry->set_default_instance(entry);
@@ -250,10 +259,13 @@ class MapEntry : public MapEntryBase {
}
private:
- MapEntry() : default_instance_(NULL), entry_lite_() {}
+ MapEntry()
+ : _internal_metadata_(NULL), default_instance_(NULL), entry_lite_() {}
explicit MapEntry(Arena* arena)
- : default_instance_(NULL), entry_lite_(arena) {}
+ : _internal_metadata_(arena),
+ default_instance_(NULL),
+ entry_lite_(arena) {}
inline Arena* GetArenaNoVirtual() const {
return entry_lite_.GetArenaNoVirtual();
@@ -266,6 +278,7 @@ class MapEntry : public MapEntryBase {
static int offsets_[2];
UnknownFieldSet _unknown_fields_;
+ InternalMetadataWithArena _internal_metadata_;
MapEntry* default_instance_;
EntryLiteType entry_lite_;
diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h
index 52746da5..7cdf1b93 100644
--- a/src/google/protobuf/map_entry_lite.h
+++ b/src/google/protobuf/map_entry_lite.h
@@ -61,38 +61,21 @@ template <typename Key, typename Value,
WireFormatLite::FieldType kValueFieldType,
int default_enum_value>
class MapEntryLite : public MessageLite {
- // Handlers for key/value wire type. Provide utilities to parse/serialize
- // key/value.
- typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler;
- typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler;
-
- // Define key/value's internal stored type. Message is the only one whose
- // internal stored type cannot be inferred from its proto type
- static const bool kIsKeyMessage = KeyWireHandler::kIsMessage;
- static const bool kIsValueMessage = ValueWireHandler::kIsMessage;
- typedef typename KeyWireHandler::CppType KeyInternalType;
- typedef typename ValueWireHandler::CppType ValueInternalType;
- typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type
- KeyCppType;
- typedef typename MapIf<kIsValueMessage, Value, ValueInternalType>::type
- ValCppType;
-
- // Handlers for key/value's internal stored type. Provide utilities to
- // manipulate internal stored type. We need it because some types are stored
- // as values and others are stored as pointers (Message and string), but we
- // need to keep the code in MapEntry unified instead of providing different
- // codes for each type.
- typedef MapCppTypeHandler<KeyCppType> KeyCppHandler;
- typedef MapCppTypeHandler<ValCppType> ValueCppHandler;
+ // Provide utilities to parse/serialize key/value. Provide utilities to
+ // manipulate internal stored type.
+ typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
+ typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
// Define internal memory layout. Strings and messages are stored as
// pointers, while other types are stored as values.
- static const bool kKeyIsStringOrMessage = KeyCppHandler::kIsStringOrMessage;
- static const bool kValIsStringOrMessage = ValueCppHandler::kIsStringOrMessage;
- typedef typename MapIf<kKeyIsStringOrMessage, KeyCppType*, KeyCppType>::type
- KeyBase;
- typedef typename MapIf<kValIsStringOrMessage, ValCppType*, ValCppType>::type
- ValueBase;
+ typedef typename KeyTypeHandler::TypeOnMemory KeyOnMemory;
+ typedef typename ValueTypeHandler::TypeOnMemory ValueOnMemory;
+
+ // Enum type cannot be used for MapTypeHandler::Read. Define a type
+ // which will replace Enum with int.
+ typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType;
+ typedef typename ValueTypeHandler::MapEntryAccessorType
+ ValueMapEntryAccessorType;
// Constants for field number.
static const int kKeyFieldNumber = 1;
@@ -100,38 +83,37 @@ class MapEntryLite : public MessageLite {
// Constants for field tag.
static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
- kKeyFieldNumber, KeyWireHandler::kWireType);
+ kKeyFieldNumber, KeyTypeHandler::kWireType);
static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
- kValueFieldNumber, ValueWireHandler::kWireType);
+ kValueFieldNumber, ValueTypeHandler::kWireType);
static const int kTagSize = 1;
public:
~MapEntryLite() {
if (this != default_instance_) {
- KeyCppHandler::Delete(key_);
- ValueCppHandler::Delete(value_);
+ if (GetArenaNoVirtual() != NULL) return;
+ KeyTypeHandler::DeleteNoArena(key_);
+ ValueTypeHandler::DeleteNoArena(value_);
}
}
// accessors ======================================================
- virtual inline const KeyCppType& key() const {
- return KeyCppHandler::Reference(key_);
- }
- inline KeyCppType* mutable_key() {
- set_has_key();
- KeyCppHandler::EnsureMutable(&key_, GetArenaNoVirtual());
- return KeyCppHandler::Pointer(key_);
+ virtual inline const KeyMapEntryAccessorType& key() const {
+ return KeyTypeHandler::GetExternalReference(key_);
}
- virtual inline const ValCppType& value() const {
+ virtual inline const ValueMapEntryAccessorType& value() const {
GOOGLE_CHECK(default_instance_ != NULL);
- return ValueCppHandler::DefaultIfNotInitialized(value_,
+ return ValueTypeHandler::DefaultIfNotInitialized(value_,
default_instance_->value_);
}
- inline ValCppType* mutable_value() {
+ inline KeyMapEntryAccessorType* mutable_key() {
+ set_has_key();
+ return KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual());
+ }
+ inline ValueMapEntryAccessorType* mutable_value() {
set_has_value();
- ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual());
- return ValueCppHandler::Pointer(value_);
+ return ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual());
}
// implements MessageLite =========================================
@@ -159,13 +141,17 @@ class MapEntryLite : public MessageLite {
tag = input->ReadTag();
switch (tag) {
case kKeyTag:
- if (!KeyWireHandler::Read(input, mutable_key())) return false;
+ if (!KeyTypeHandler::Read(input, mutable_key())) {
+ return false;
+ }
set_has_key();
if (!input->ExpectTag(kValueTag)) break;
GOOGLE_FALLTHROUGH_INTENDED;
case kValueTag:
- if (!ValueWireHandler::Read(input, mutable_value())) return false;
+ if (!ValueTypeHandler::Read(input, mutable_value())) {
+ return false;
+ }
set_has_value();
if (input->ExpectAtEnd()) return true;
break;
@@ -184,32 +170,35 @@ class MapEntryLite : public MessageLite {
int ByteSize() const {
int size = 0;
- size += has_key() ? kTagSize + KeyWireHandler::ByteSize(key()) : 0;
- size += has_value() ? kTagSize + ValueWireHandler::ByteSize(value()) : 0;
+ size += has_key() ? kTagSize + KeyTypeHandler::ByteSize(key()) : 0;
+ size += has_value() ? kTagSize + ValueTypeHandler::ByteSize(value()) : 0;
return size;
}
void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
- KeyWireHandler::Write(kKeyFieldNumber, key(), output);
- ValueWireHandler::Write(kValueFieldNumber, value(), output);
+ KeyTypeHandler::Write(kKeyFieldNumber, key(), output);
+ ValueTypeHandler::Write(kValueFieldNumber, value(), output);
}
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
- output = KeyWireHandler::WriteToArray(kKeyFieldNumber, key(), output);
- output =
- ValueWireHandler::WriteToArray(kValueFieldNumber, value(), output);
+ output = KeyTypeHandler::WriteToArray(kKeyFieldNumber, key(), output);
+ output = ValueTypeHandler::WriteToArray(kValueFieldNumber, value(), output);
return output;
}
int GetCachedSize() const {
int size = 0;
- size += has_key() ? kTagSize + KeyWireHandler::GetCachedSize(key()) : 0;
- size +=
- has_value() ? kTagSize + ValueWireHandler::GetCachedSize(value()) : 0;
+ size += has_key()
+ ? kTagSize + KeyTypeHandler::GetCachedSize(key())
+ : 0;
+ size += has_value()
+ ? kTagSize + ValueTypeHandler::GetCachedSize(
+ value())
+ : 0;
return size;
}
- bool IsInitialized() const { return ValueCppHandler::IsInitialized(value_); }
+ bool IsInitialized() const { return ValueTypeHandler::IsInitialized(value_); }
MessageLite* New() const {
MapEntryLite* entry = new MapEntryLite;
@@ -225,36 +214,37 @@ class MapEntryLite : public MessageLite {
int SpaceUsed() const {
int size = sizeof(MapEntryLite);
- size += KeyCppHandler::SpaceUsedInMapEntry(key_);
- size += ValueCppHandler::SpaceUsedInMapEntry(value_);
+ size += KeyTypeHandler::SpaceUsedInMapEntry(key_);
+ size += ValueTypeHandler::SpaceUsedInMapEntry(value_);
return size;
}
void MergeFrom(const MapEntryLite& from) {
if (from._has_bits_[0]) {
if (from.has_key()) {
- KeyCppHandler::EnsureMutable(&key_, GetArenaNoVirtual());
- KeyCppHandler::Merge(from.key(), &key_);
+ KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual());
+ KeyTypeHandler::Merge(from.key(), &key_, GetArenaNoVirtual());
set_has_key();
}
if (from.has_value()) {
- ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual());
- ValueCppHandler::Merge(from.value(), &value_);
+ ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual());
+ ValueTypeHandler::Merge(from.value(), &value_, GetArenaNoVirtual());
set_has_value();
}
}
}
void Clear() {
- KeyCppHandler::Clear(&key_);
- ValueCppHandler::ClearMaybeByDefaultEnum(&value_, default_enum_value);
+ KeyTypeHandler::Clear(&key_, GetArenaNoVirtual());
+ ValueTypeHandler::ClearMaybeByDefaultEnum(
+ &value_, GetArenaNoVirtual(), default_enum_value);
clear_has_key();
clear_has_value();
}
void InitAsDefaultInstance() {
- KeyCppHandler::AssignDefaultValue(&key_);
- ValueCppHandler::AssignDefaultValue(&value_);
+ KeyTypeHandler::AssignDefaultValue(&key_);
+ ValueTypeHandler::AssignDefaultValue(&value_);
}
Arena* GetArena() const {
@@ -305,8 +295,8 @@ class MapEntryLite : public MessageLite {
class MapEntryWrapper
: public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> {
typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base;
- typedef typename Base::KeyCppType KeyCppType;
- typedef typename Base::ValCppType ValCppType;
+ typedef typename Base::KeyMapEntryAccessorType KeyMapEntryAccessorType;
+ typedef typename Base::ValueMapEntryAccessorType ValueMapEntryAccessorType;
public:
MapEntryWrapper(Arena* arena, const K& key, const V& value)
@@ -316,8 +306,8 @@ class MapEntryLite : public MessageLite {
Base::set_has_key();
Base::set_has_value();
}
- inline const KeyCppType& key() const { return key_; }
- inline const ValCppType& value() const { return value_; }
+ inline const KeyMapEntryAccessorType& key() const { return key_; }
+ inline const ValueMapEntryAccessorType& value() const { return value_; }
private:
const Key& key_;
@@ -339,8 +329,8 @@ class MapEntryLite : public MessageLite {
class MapEnumEntryWrapper
: public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> {
typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base;
- typedef typename Base::KeyCppType KeyCppType;
- typedef typename Base::ValCppType ValCppType;
+ typedef typename Base::KeyMapEntryAccessorType KeyMapEntryAccessorType;
+ typedef typename Base::ValueMapEntryAccessorType ValueMapEntryAccessorType;
public:
MapEnumEntryWrapper(Arena* arena, const K& key, const V& value)
@@ -350,28 +340,28 @@ class MapEntryLite : public MessageLite {
Base::set_has_key();
Base::set_has_value();
}
- inline const KeyCppType& key() const { return key_; }
- inline const ValCppType& value() const { return value_; }
+ inline const KeyMapEntryAccessorType& key() const { return key_; }
+ inline const ValueMapEntryAccessorType& value() const { return value_; }
private:
- const KeyCppType& key_;
- const ValCppType value_;
+ const KeyMapEntryAccessorType& key_;
+ const ValueMapEntryAccessorType value_;
friend class google::protobuf::Arena;
typedef void DestructorSkippable_;
};
MapEntryLite() : default_instance_(NULL), arena_(NULL) {
- KeyCppHandler::Initialize(&key_, NULL);
- ValueCppHandler::InitializeMaybeByDefaultEnum(
+ KeyTypeHandler::Initialize(&key_, NULL);
+ ValueTypeHandler::InitializeMaybeByDefaultEnum(
&value_, default_enum_value, NULL);
_has_bits_[0] = 0;
}
explicit MapEntryLite(Arena* arena)
: default_instance_(NULL), arena_(arena) {
- KeyCppHandler::Initialize(&key_, arena);
- ValueCppHandler::InitializeMaybeByDefaultEnum(
+ KeyTypeHandler::Initialize(&key_, arena);
+ ValueTypeHandler::InitializeMaybeByDefaultEnum(
&value_, default_enum_value, arena);
_has_bits_[0] = 0;
}
@@ -386,8 +376,8 @@ class MapEntryLite : public MessageLite {
MapEntryLite* default_instance_;
- KeyBase key_;
- ValueBase value_;
+ KeyOnMemory key_;
+ ValueOnMemory value_;
Arena* arena_;
uint32 _has_bits_[1];
diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc
index 6ff1936e..eddc95c4 100644
--- a/src/google/protobuf/map_field.cc
+++ b/src/google/protobuf/map_field.cc
@@ -29,6 +29,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <google/protobuf/map_field.h>
+#include <google/protobuf/map_field_inl.h>
#include <vector>
@@ -145,6 +146,321 @@ void MapFieldBase::SyncMapWithRepeatedField() const {
}
}
+// ------------------DynamicMapField------------------
+DynamicMapField::DynamicMapField(const Message* default_entry)
+ : default_entry_(default_entry) {
+}
+
+DynamicMapField::DynamicMapField(const Message* default_entry,
+ Arena* arena)
+ : TypeDefinedMapFieldBase<MapKey, MapValueRef>(arena),
+ default_entry_(default_entry) {
+}
+
+DynamicMapField::~DynamicMapField() {
+ // DynamicMapField owns map values. Need to delete them before clearing
+ // the map.
+ for (Map<MapKey, MapValueRef>::iterator iter = map_.begin();
+ iter != map_.end(); ++iter) {
+ iter->second.DeleteData();
+ }
+ map_.clear();
+}
+
+int DynamicMapField::size() const {
+ return GetMap().size();
+}
+
+bool DynamicMapField::ContainsMapKey(
+ const MapKey& map_key) const {
+ const Map<MapKey, MapValueRef>& map = GetMap();
+ Map<MapKey, MapValueRef>::const_iterator iter = map.find(map_key);
+ return iter != map.end();
+}
+
+bool DynamicMapField::InsertMapValue(
+ 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;
+ 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
+ // default value.
+ switch (val_des->cpp_type()) {
+#define HANDLE_TYPE(CPPTYPE, TYPE) \
+ case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \
+ TYPE * value = new TYPE(); \
+ map_val.SetValue(value); \
+ break; \
+ }
+ HANDLE_TYPE(INT32, int32);
+ HANDLE_TYPE(INT64, int64);
+ HANDLE_TYPE(UINT32, uint32);
+ HANDLE_TYPE(UINT64, uint64);
+ HANDLE_TYPE(DOUBLE, double);
+ HANDLE_TYPE(FLOAT, float);
+ HANDLE_TYPE(BOOL, bool);
+ HANDLE_TYPE(STRING, string);
+ HANDLE_TYPE(ENUM, int32);
+#undef HANDLE_TYPE
+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
+ const Message& message = default_entry_->GetReflection()->GetMessage(
+ *default_entry_, val_des);
+ Message* value = message.New();
+ map_val.SetValue(value);
+ break;
+ }
+ }
+ }
+ val->CopyFrom(map_val);
+ return result;
+}
+
+bool DynamicMapField::DeleteMapValue(const MapKey& map_key) {
+ MapFieldBase::SyncMapWithRepeatedField();
+ Map<MapKey, MapValueRef>::iterator iter = map_.find(map_key);
+ if (iter == map_.end()) {
+ return false;
+ }
+ // Set map dirty only if the delete is successful.
+ MapFieldBase::SetMapDirty();
+ iter->second.DeleteData();
+ map_.erase(iter);
+ return true;
+}
+
+const Map<MapKey, MapValueRef>& DynamicMapField::GetMap() const {
+ MapFieldBase::SyncMapWithRepeatedField();
+ return map_;
+}
+
+Map<MapKey, MapValueRef>* DynamicMapField::MutableMap() {
+ MapFieldBase::SyncMapWithRepeatedField();
+ MapFieldBase::SetMapDirty();
+ return &map_;
+}
+
+void DynamicMapField::SetMapIteratorValue(MapIterator* map_iter) const {
+ Map<MapKey, MapValueRef>::const_iterator iter =
+ TypeDefinedMapFieldBase<MapKey, MapValueRef>::InternalGetIterator(
+ map_iter);
+ if (iter == map_.end()) return;
+ map_iter->key_.CopyFrom(iter->first);
+ map_iter->value_.CopyFrom(iter->second);
+}
+
+void DynamicMapField::SyncRepeatedFieldWithMapNoLock() const {
+ const Reflection* reflection = default_entry_->GetReflection();
+ const FieldDescriptor* key_des =
+ default_entry_->GetDescriptor()->FindFieldByName("key");
+ const FieldDescriptor* val_des =
+ default_entry_->GetDescriptor()->FindFieldByName("value");
+ if (MapFieldBase::repeated_field_ == NULL) {
+ if (MapFieldBase::arena_ == NULL) {
+ MapFieldBase::repeated_field_ = new RepeatedPtrField<Message>();
+ } else {
+ MapFieldBase::repeated_field_ =
+ Arena::CreateMessage<RepeatedPtrField<Message> >(
+ MapFieldBase::arena_);
+ }
+ }
+
+ MapFieldBase::repeated_field_->Clear();
+
+ for (Map<MapKey, MapValueRef>::const_iterator it = map_.begin();
+ it != map_.end(); ++it) {
+ Message* new_entry = default_entry_->New();
+ MapFieldBase::repeated_field_->AddAllocated(new_entry);
+ const MapKey& map_key = it->first;
+ switch (key_des->cpp_type()) {
+ case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
+ reflection->SetString(new_entry, key_des, map_key.GetStringValue());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
+ reflection->SetInt64(new_entry, key_des, map_key.GetInt64Value());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
+ reflection->SetInt32(new_entry, key_des, map_key.GetInt32Value());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
+ reflection->SetUInt64(new_entry, key_des, map_key.GetUInt64Value());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
+ reflection->SetUInt32(new_entry, key_des, map_key.GetUInt32Value());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
+ reflection->SetBool(new_entry, key_des, map_key.GetBoolValue());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
+ case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
+ case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ break;
+ }
+ const MapValueRef& map_val = it->second;
+ switch (val_des->cpp_type()) {
+ case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
+ reflection->SetString(new_entry, val_des, map_val.GetStringValue());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
+ reflection->SetInt64(new_entry, val_des, map_val.GetInt64Value());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
+ reflection->SetInt32(new_entry, val_des, map_val.GetInt32Value());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
+ reflection->SetUInt64(new_entry, val_des, map_val.GetUInt64Value());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
+ reflection->SetUInt32(new_entry, val_des, map_val.GetUInt32Value());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
+ reflection->SetBool(new_entry, val_des, map_val.GetBoolValue());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
+ reflection->SetDouble(new_entry, val_des, map_val.GetDoubleValue());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
+ reflection->SetFloat(new_entry, val_des, map_val.GetFloatValue());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
+ reflection->SetEnumValue(new_entry, val_des, map_val.GetEnumValue());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
+ const Message& message = map_val.GetMessageValue();
+ reflection->MutableMessage(new_entry, val_des)->CopyFrom(message);
+ break;
+ }
+ }
+ }
+}
+
+void DynamicMapField::SyncMapWithRepeatedFieldNoLock() const {
+ Map<MapKey, MapValueRef>* map = &const_cast<DynamicMapField*>(this)->map_;
+ const Reflection* reflection = default_entry_->GetReflection();
+ const FieldDescriptor* key_des =
+ default_entry_->GetDescriptor()->FindFieldByName("key");
+ const FieldDescriptor* val_des =
+ default_entry_->GetDescriptor()->FindFieldByName("value");
+ // DynamicMapField owns map values. Need to delete them before clearing
+ // the map.
+ for (Map<MapKey, MapValueRef>::iterator iter = map->begin();
+ iter != map->end(); ++iter) {
+ iter->second.DeleteData();
+ }
+ map->clear();
+ for (RepeatedPtrField<Message>::iterator it =
+ MapFieldBase::repeated_field_->begin();
+ it != MapFieldBase::repeated_field_->end(); ++it) {
+ MapKey map_key;
+ switch (key_des->cpp_type()) {
+ case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
+ map_key.SetStringValue(reflection->GetString(*it, key_des));
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
+ map_key.SetInt64Value(reflection->GetInt64(*it, key_des));
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
+ map_key.SetInt32Value(reflection->GetInt32(*it, key_des));
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
+ map_key.SetUInt64Value(reflection->GetUInt64(*it, key_des));
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
+ map_key.SetUInt32Value(reflection->GetUInt32(*it, key_des));
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
+ map_key.SetBoolValue(reflection->GetBool(*it, key_des));
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
+ case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
+ case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ break;
+ }
+ MapValueRef& map_val = (*map)[map_key];
+ map_val.SetType(val_des->cpp_type());
+ switch (val_des->cpp_type()) {
+#define HANDLE_TYPE(CPPTYPE, TYPE, METHOD) \
+ case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \
+ TYPE * value = new TYPE; \
+ *value = reflection->Get##METHOD(*it, val_des); \
+ map_val.SetValue(value); \
+ break; \
+ }
+ HANDLE_TYPE(INT32, int32, Int32);
+ HANDLE_TYPE(INT64, int64, Int64);
+ HANDLE_TYPE(UINT32, uint32, UInt32);
+ HANDLE_TYPE(UINT64, uint64, UInt64);
+ HANDLE_TYPE(DOUBLE, double, Double);
+ HANDLE_TYPE(FLOAT, float, Float);
+ HANDLE_TYPE(BOOL, bool, Bool);
+ HANDLE_TYPE(STRING, string, String);
+ HANDLE_TYPE(ENUM, int32, EnumValue);
+#undef HANDLE_TYPE
+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
+ const Message& message = reflection->GetMessage(*it, val_des);
+ Message* value = message.New();
+ value->CopyFrom(message);
+ map_val.SetValue(value);
+ break;
+ }
+ }
+ }
+}
+
+int DynamicMapField::SpaceUsedExcludingSelfNoLock() const {
+ int size = 0;
+ if (MapFieldBase::repeated_field_ != NULL) {
+ size += MapFieldBase::repeated_field_->SpaceUsedExcludingSelf();
+ }
+ size += sizeof(map_);
+ int map_size = map_.size();
+ if (map_size) {
+ Map<MapKey, MapValueRef>::const_iterator it = map_.begin();
+ size += sizeof(it->first) * map_size;
+ size += sizeof(it->second) * map_size;
+ // If key is string, add the allocated space.
+ if (it->first.type() == google::protobuf::FieldDescriptor::CPPTYPE_STRING) {
+ size += sizeof(string) * map_size;
+ }
+ // Add the allocated space in MapValueRef.
+ switch (it->second.type()) {
+#define HANDLE_TYPE(CPPTYPE, TYPE) \
+ case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \
+ size += sizeof(TYPE) * map_size; \
+ break; \
+ }
+ HANDLE_TYPE(INT32, int32);
+ HANDLE_TYPE(INT64, int64);
+ HANDLE_TYPE(UINT32, uint32);
+ HANDLE_TYPE(UINT64, uint64);
+ HANDLE_TYPE(DOUBLE, double);
+ HANDLE_TYPE(FLOAT, float);
+ HANDLE_TYPE(BOOL, bool);
+ HANDLE_TYPE(STRING, string);
+ HANDLE_TYPE(ENUM, int32);
+#undef HANDLE_TYPE
+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
+ while (it != map_.end()) {
+ const Message& message = it->second.GetMessageValue();
+ size += message.GetReflection()->SpaceUsed(message);
+ ++it;
+ }
+ break;
+ }
+ }
+ }
+ return size;
+}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h
index 56d3d0f4..9130166b 100644
--- a/src/google/protobuf/map_field.h
+++ b/src/google/protobuf/map_field.h
@@ -32,6 +32,7 @@
#define GOOGLE_PROTOBUF_MAP_FIELD_H__
#include <google/protobuf/stubs/atomicops.h>
+#include <google/protobuf/stubs/mutex.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/arena.h>
@@ -45,7 +46,8 @@
namespace google {
namespace protobuf {
-
+class DynamicMessage;
+class MapKey;
namespace internal {
class ContendedMapCleanTest;
@@ -83,6 +85,17 @@ class LIBPROTOBUF_EXPORT MapFieldBase {
// Like above. Returns mutable pointer to the internal repeated field.
RepeatedPtrFieldBase* MutableRepeatedField();
+ // 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 DeleteMapValue(const MapKey& map_key) = 0;
+ virtual bool EqualIterator(const MapIterator& a,
+ const MapIterator& b) const = 0;
+ virtual void MapBegin(MapIterator* map_iter) const = 0;
+ virtual void MapEnd(MapIterator* map_iter) const = 0;
+ // Sync Map with repeated field and returns the size of map.
+ virtual int size() const = 0;
+
// Returns the number of bytes used by the repeated field, excluding
// sizeof(*this)
int SpaceUsedExcludingSelf() const;
@@ -141,6 +154,57 @@ class LIBPROTOBUF_EXPORT MapFieldBase {
friend class ContendedMapCleanTest;
friend class GeneratedMessageReflection;
friend class MapFieldAccessor;
+ friend class ::google::protobuf::DynamicMessage;
+
+ // Virtual helper methods for MapIterator. MapIterator doesn't have the
+ // type helper for key and value. Call these help methods to deal with
+ // different types. Real helper methods are implemented in
+ // TypeDefinedMapFieldBase.
+ friend class ::google::protobuf::MapIterator;
+ // Allocate map<...>::iterator for MapIterator.
+ virtual void InitializeIterator(MapIterator* map_iter) const = 0;
+
+ // DeleteIterator() is called by the destructor of MapIterator only.
+ // It deletes map<...>::iterator for MapIterator.
+ virtual void DeleteIterator(MapIterator* map_iter) const = 0;
+
+ // Copy the map<...>::iterator from other_iterator to
+ // this_iterator.
+ virtual void CopyIterator(MapIterator* this_iterator,
+ const MapIterator& other_iterator) const = 0;
+
+ // IncreaseIterator() is called by operator++() of MapIterator only.
+ // It implements the ++ operator of MapIterator.
+ virtual void IncreaseIterator(MapIterator* map_iter) const = 0;
+};
+
+// This class provides common Map Reflection implementations for generated
+// message and dynamic message.
+template<typename Key, typename T>
+class TypeDefinedMapFieldBase : public MapFieldBase {
+ public:
+ TypeDefinedMapFieldBase() {}
+ explicit TypeDefinedMapFieldBase(Arena* arena) : MapFieldBase(arena) {}
+ ~TypeDefinedMapFieldBase() {}
+ void MapBegin(MapIterator* map_iter) const;
+ void MapEnd(MapIterator* map_iter) const;
+ bool EqualIterator(const MapIterator& a, const MapIterator& b) const;
+
+ virtual const Map<Key, T>& GetMap() const = 0;
+ virtual Map<Key, T>* MutableMap() = 0;
+
+ protected:
+ typename Map<Key, T>::const_iterator& InternalGetIterator(
+ const MapIterator* map_iter) const;
+
+ private:
+ void InitializeIterator(MapIterator* map_iter) const;
+ void DeleteIterator(MapIterator* map_iter) const;
+ void CopyIterator(MapIterator* this_iteratorm,
+ const MapIterator& that_iterator) const;
+ void IncreaseIterator(MapIterator* map_iter) const;
+
+ virtual void SetMapIteratorValue(MapIterator* map_iter) const = 0;
};
// This class provides accesss to map field using generated api. It is used for
@@ -150,25 +214,13 @@ template <typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType,
int default_enum_value = 0>
-class MapField : public MapFieldBase,
+class MapField : public TypeDefinedMapFieldBase<Key, T>,
public MapFieldLite<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value> {
- // Handlers for key/value wire type. Provide utilities to parse/serialize
- // key/value.
- typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler;
- typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler;
-
- // Define key/value's internal stored type.
- static const bool kIsKeyMessage = KeyWireHandler::kIsMessage;
- static const bool kIsValMessage = ValueWireHandler::kIsMessage;
- typedef typename KeyWireHandler::CppType KeyInternalType;
- typedef typename ValueWireHandler::CppType ValueInternalType;
- typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type KeyCpp;
- typedef typename MapIf<kIsValMessage, T , ValueInternalType>::type ValCpp;
-
- // Handlers for key/value's internal stored type.
- typedef MapCppTypeHandler<KeyCpp> KeyHandler;
- typedef MapCppTypeHandler<ValCpp> ValHandler;
+ // Provide utilities to parse/serialize key/value. Provide utilities to
+ // manipulate internal stored type.
+ typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
+ typedef MapTypeHandler<kValueFieldType, T> ValueTypeHandler;
// Define message type for internal repeated field.
typedef MapEntry<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>
@@ -183,8 +235,8 @@ class MapField : public MapFieldBase,
// Enum needs to be handled differently from other types because it has
// different exposed type in google::protobuf::Map's api and repeated field's api. For
// details see the comment in the implementation of
- // SyncMapWithRepeatedFieldNoLocki.
- static const bool kIsValueEnum = ValueWireHandler::kIsEnum;
+ // SyncMapWithRepeatedFieldNoLock.
+ static const bool kIsValueEnum = ValueTypeHandler::kIsEnum;
typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType;
public:
@@ -197,6 +249,11 @@ class MapField : public MapFieldBase,
MapField(Arena* arena, const Message* default_entry);
~MapField();
+ // Implement MapFieldBase
+ bool ContainsMapKey(const MapKey& map_key) const;
+ bool InsertMapValue(const MapKey& map_key, MapValueRef* val);
+ bool DeleteMapValue(const MapKey& map_key);
+
// Accessors
const Map<Key, T>& GetMap() const;
Map<Key, T>* MutableMap();
@@ -230,12 +287,109 @@ class MapField : public MapFieldBase,
void SyncMapWithRepeatedFieldNoLock() const;
int SpaceUsedExcludingSelfNoLock() const;
+ void SetMapIteratorValue(MapIterator* map_iter) const;
+
mutable const EntryType* default_entry_;
friend class ::google::protobuf::Arena;
};
+class LIBPROTOBUF_EXPORT DynamicMapField: public TypeDefinedMapFieldBase<MapKey, MapValueRef> {
+ public:
+ explicit DynamicMapField(const Message* default_entry);
+ DynamicMapField(const Message* default_entry, Arena* arena);
+ ~DynamicMapField();
+
+ // Implement MapFieldBase
+ bool ContainsMapKey(const MapKey& map_key) const;
+ bool InsertMapValue(const MapKey& map_key, MapValueRef* val);
+ bool DeleteMapValue(const MapKey& map_key);
+
+ const Map<MapKey, MapValueRef>& GetMap() const;
+ Map<MapKey, MapValueRef>* MutableMap();
+
+ int size() const;
+
+ private:
+ Map<MapKey, MapValueRef> map_;
+ const Message* default_entry_;
+
+ // Implements MapFieldBase
+ void SyncRepeatedFieldWithMapNoLock() const;
+ void SyncMapWithRepeatedFieldNoLock() const;
+ int SpaceUsedExcludingSelfNoLock() const;
+ void SetMapIteratorValue(MapIterator* map_iter) const;
+};
+
} // namespace internal
+
+class LIBPROTOBUF_EXPORT MapIterator {
+ public:
+ MapIterator(Message* message, const FieldDescriptor* field) {
+ const Reflection* reflection = message->GetReflection();
+ map_ = reflection->MapData(message, field);
+ key_.SetType(field->message_type()->FindFieldByName("key")->cpp_type());
+ value_.SetType(field->message_type()->FindFieldByName("value")->cpp_type());
+ map_->InitializeIterator(this);
+ }
+ MapIterator(const MapIterator& other) {
+ map_ = other.map_;
+ map_->InitializeIterator(this);
+ map_->CopyIterator(this, other);
+ }
+ ~MapIterator() {
+ map_->DeleteIterator(this);
+ }
+ friend bool operator==(const MapIterator& a, const MapIterator& b) {
+ return a.map_->EqualIterator(a, b);
+ }
+ friend bool operator!=(const MapIterator& a, const MapIterator& b) {
+ return !a.map_->EqualIterator(a, b);
+ }
+ MapIterator& operator++() {
+ map_->IncreaseIterator(this);
+ return *this;
+ }
+ MapIterator operator++(int) {
+ // iter_ is copied from Map<...>::iterator, no need to
+ // copy from its self again. Use the same implementation
+ // with operator++()
+ map_->IncreaseIterator(this);
+ return *this;
+ }
+ const MapKey& GetKey() {
+ return key_;
+ }
+ const MapValueRef& GetValueRef() {
+ return value_;
+ }
+ MapValueRef* MutableValueRef() {
+ map_->SetMapDirty();
+ return &value_;
+ }
+
+ private:
+ template <typename Key, typename T>
+ friend class internal::TypeDefinedMapFieldBase;
+ friend class internal::DynamicMapField;
+ template <typename Key, typename T,
+ internal::WireFormatLite::FieldType kKeyFieldType,
+ internal::WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+ friend class internal::MapField;
+
+ // reinterpret_cast from heap-allocated Map<...>::iterator*. MapIterator owns
+ // the iterator. It is allocated by MapField<...>::InitializeIterator() called
+ // in constructor and deleted by MapField<...>::DeleteIterator() called in
+ // destructor.
+ void* iter_;
+ // Point to a MapField to call helper methods implemented in MapField.
+ // MapIterator does not own this object.
+ internal::MapFieldBase* map_;
+ MapKey key_;
+ MapValueRef value_;
+};
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h
index 5b4305f9..16c4a08f 100644
--- a/src/google/protobuf/map_field_inl.h
+++ b/src/google/protobuf/map_field_inl.h
@@ -36,12 +36,130 @@
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <google/protobuf/map.h>
#include <google/protobuf/map_field.h>
#include <google/protobuf/map_type_handler.h>
namespace google {
namespace protobuf {
namespace internal {
+// UnwrapMapKey template
+template<typename T>
+T UnwrapMapKey(const MapKey& map_key);
+template<>
+inline int32 UnwrapMapKey<int32>(const MapKey& map_key) {
+ return map_key.GetInt32Value();
+}
+template<>
+inline uint32 UnwrapMapKey<uint32>(const MapKey& map_key) {
+ return map_key.GetUInt32Value();
+}
+template<>
+inline int64 UnwrapMapKey<int64>(const MapKey& map_key) {
+ return map_key.GetInt64Value();
+}
+template<>
+inline uint64 UnwrapMapKey<uint64>(const MapKey& map_key) {
+ return map_key.GetUInt64Value();
+}
+template<>
+inline bool UnwrapMapKey<bool>(const MapKey& map_key) {
+ return map_key.GetBoolValue();
+}
+template<>
+inline string UnwrapMapKey<string>(const MapKey& map_key) {
+ return map_key.GetStringValue();
+}
+
+// SetMapKey template
+template<typename T>
+inline void SetMapKey(MapKey* map_key, const T& value);
+template<>
+inline void SetMapKey<int32>(MapKey* map_key, const int32& value) {
+ map_key->SetInt32Value(value);
+}
+template<>
+inline void SetMapKey<uint32>(MapKey* map_key, const uint32& value) {
+ map_key->SetUInt32Value(value);
+}
+template<>
+inline void SetMapKey<int64>(MapKey* map_key, const int64& value) {
+ map_key->SetInt64Value(value);
+}
+template<>
+inline void SetMapKey<uint64>(MapKey* map_key, const uint64& value) {
+ map_key->SetUInt64Value(value);
+}
+template<>
+inline void SetMapKey<bool>(MapKey* map_key, const bool& value) {
+ map_key->SetBoolValue(value);
+}
+template<>
+inline void SetMapKey<string>(MapKey* map_key, const string& value) {
+ map_key->SetStringValue(value);
+}
+
+// ------------------------TypeDefinedMapFieldBase---------------
+template <typename Key, typename T>
+typename Map<Key, T>::const_iterator&
+TypeDefinedMapFieldBase<Key, T>::InternalGetIterator(
+ const MapIterator* map_iter) const {
+ return *reinterpret_cast<typename Map<Key, T>::const_iterator *>(
+ map_iter->iter_);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::MapBegin(MapIterator* map_iter) const {
+ InternalGetIterator(map_iter) = GetMap().begin();
+ SetMapIteratorValue(map_iter);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::MapEnd(MapIterator* map_iter) const {
+ InternalGetIterator(map_iter) = GetMap().end();
+}
+
+template <typename Key, typename T>
+bool TypeDefinedMapFieldBase<Key, T>::EqualIterator(const MapIterator& a,
+ const MapIterator& b)
+ const {
+ return InternalGetIterator(&a) == InternalGetIterator(&b);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::IncreaseIterator(MapIterator* map_iter)
+ const {
+ ++InternalGetIterator(map_iter);
+ SetMapIteratorValue(map_iter);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::InitializeIterator(
+ MapIterator* map_iter) const {
+ map_iter->iter_ = new typename Map<Key, T>::const_iterator;
+ GOOGLE_CHECK(map_iter->iter_ != NULL);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::DeleteIterator(MapIterator* map_iter)
+ const {
+ delete reinterpret_cast<typename Map<Key, T>::const_iterator *>(
+ map_iter->iter_);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::CopyIterator(
+ MapIterator* this_iter,
+ const MapIterator& that_iter) const {
+ InternalGetIterator(this_iter) = InternalGetIterator(&that_iter);
+ this_iter->key_.SetType(that_iter.key_.type());
+ // MapValueRef::type() fails when containing data is null. However, if
+ // this_iter points to MapEnd, data can be null.
+ this_iter->value_.SetType((FieldDescriptor::CppType)that_iter.value_.type_);
+ SetMapIteratorValue(this_iter);
+}
+
+// ----------------------------------------------------------------------
template <typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
@@ -56,7 +174,7 @@ template <typename Key, typename T,
int default_enum_value>
MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField(
Arena* arena)
- : MapFieldBase(arena),
+ : TypeDefinedMapFieldBase<Key, T>(arena),
MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>(
arena),
default_entry_(NULL) {}
@@ -75,7 +193,7 @@ template <typename Key, typename T,
int default_enum_value>
MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField(
Arena* arena, const Message* default_entry)
- : MapFieldBase(arena),
+ : TypeDefinedMapFieldBase<Key, T>(arena),
MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>(
arena),
default_entry_(down_cast<const EntryType*>(default_entry)) {}
@@ -94,7 +212,7 @@ template <typename Key, typename T,
int
MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::size() const {
- SyncMapWithRepeatedField();
+ MapFieldBase::SyncMapWithRepeatedField();
return MapFieldLiteType::GetInternalMap().size();
}
@@ -105,9 +223,65 @@ template <typename Key, typename T,
void
MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::Clear() {
- SyncMapWithRepeatedField();
+ MapFieldBase::SyncMapWithRepeatedField();
MapFieldLiteType::MutableInternalMap()->clear();
- SetMapDirty();
+ MapFieldBase::SetMapDirty();
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+void MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::SetMapIteratorValue(
+ MapIterator* map_iter) const {
+ const Map<Key, T>& map = GetMap();
+ typename Map<Key, T>::const_iterator iter =
+ TypeDefinedMapFieldBase<Key, T>::InternalGetIterator(map_iter);
+ if (iter == map.end()) return;
+ SetMapKey(&map_iter->key_, iter->first);
+ map_iter->value_.SetValue(&iter->second);
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+bool MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::ContainsMapKey(
+ const MapKey& map_key) const {
+ const Map<Key, T>& map = GetMap();
+ const Key& key = UnwrapMapKey<Key>(map_key);
+ typename Map<Key, T>::const_iterator iter = map.find(key);
+ return iter != map.end();
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+bool MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::InsertMapValue(const MapKey& map_key,
+ MapValueRef* val) {
+ Map<Key, T>* map = MutableMap();
+ bool result = false;
+ const Key& key = UnwrapMapKey<Key>(map_key);
+ if (map->end() == map->find(key)) {
+ result = true;
+ }
+ val->SetValue(&((*map)[key]));
+ return result;
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+bool MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::DeleteMapValue(
+ const MapKey& map_key) {
+ const Key& key = UnwrapMapKey<Key>(map_key);
+ return MutableMap()->erase(key);
}
template <typename Key, typename T,
@@ -117,7 +291,7 @@ template <typename Key, typename T,
const Map<Key, T>&
MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::GetMap() const {
- SyncMapWithRepeatedField();
+ MapFieldBase::SyncMapWithRepeatedField();
return MapFieldLiteType::GetInternalMap();
}
@@ -128,9 +302,9 @@ template <typename Key, typename T,
Map<Key, T>*
MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::MutableMap() {
- SyncMapWithRepeatedField();
+ MapFieldBase::SyncMapWithRepeatedField();
Map<Key, T>* result = MapFieldLiteType::MutableInternalMap();
- SetMapDirty();
+ MapFieldBase::SetMapDirty();
return result;
}
@@ -143,10 +317,10 @@ MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::MergeFrom(
const MapFieldLiteType& other) {
const MapField& down_other = down_cast<const MapField&>(other);
- SyncMapWithRepeatedField();
+ MapFieldBase::SyncMapWithRepeatedField();
down_other.SyncMapWithRepeatedField();
MapFieldLiteType::MergeFrom(other);
- SetMapDirty();
+ MapFieldBase::SetMapDirty();
}
template <typename Key, typename T,
@@ -158,9 +332,9 @@ MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::Swap(
MapFieldLiteType* other) {
MapField* down_other = down_cast<MapField*>(other);
- std::swap(repeated_field_, down_other->repeated_field_);
+ std::swap(MapFieldBase::repeated_field_, down_other->repeated_field_);
MapFieldLiteType::Swap(other);
- std::swap(state_, down_other->state_);
+ std::swap(MapFieldBase::state_, down_other->state_);
}
template <typename Key, typename T,
@@ -171,7 +345,7 @@ void
MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::SetEntryDescriptor(
const Descriptor** descriptor) {
- entry_descriptor_ = descriptor;
+ MapFieldBase::entry_descriptor_ = descriptor;
}
template <typename Key, typename T,
@@ -181,7 +355,7 @@ template <typename Key, typename T,
void
MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::SetAssignDescriptorCallback(void (*callback)()) {
- assign_descriptor_callback_ = callback;
+ MapFieldBase::assign_descriptor_callback_ = callback;
}
template <typename Key, typename T,
@@ -211,17 +385,19 @@ template <typename Key, typename T,
void
MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::SyncRepeatedFieldWithMapNoLock() const {
- if (repeated_field_ == NULL) {
+ if (MapFieldBase::repeated_field_ == NULL) {
if (MapFieldBase::arena_ == NULL) {
- repeated_field_ = new RepeatedPtrField<Message>();
+ MapFieldBase::repeated_field_ = new RepeatedPtrField<Message>();
} else {
- repeated_field_ = Arena::CreateMessage<RepeatedPtrField<Message> >(
- MapFieldBase::arena_);
+ MapFieldBase::repeated_field_ =
+ Arena::CreateMessage<RepeatedPtrField<Message> >(
+ MapFieldBase::arena_);
}
}
const Map<Key, T>& map = GetInternalMap();
RepeatedPtrField<EntryType>* repeated_field =
- reinterpret_cast<RepeatedPtrField<EntryType>*>(repeated_field_);
+ reinterpret_cast<RepeatedPtrField<EntryType>*>(
+ MapFieldBase::repeated_field_);
repeated_field->Clear();
@@ -246,7 +422,9 @@ MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::SyncMapWithRepeatedFieldNoLock() const {
Map<Key, T>* map = const_cast<MapField*>(this)->MutableInternalMap();
RepeatedPtrField<EntryType>* repeated_field =
- reinterpret_cast<RepeatedPtrField<EntryType>*>(repeated_field_);
+ reinterpret_cast<RepeatedPtrField<EntryType>*>(
+ MapFieldBase::repeated_field_);
+ GOOGLE_CHECK(MapFieldBase::repeated_field_ != NULL);
map->clear();
for (typename RepeatedPtrField<EntryType>::iterator it =
repeated_field->begin(); it != repeated_field->end(); ++it) {
@@ -267,15 +445,15 @@ int
MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::SpaceUsedExcludingSelfNoLock() const {
int size = 0;
- if (repeated_field_ != NULL) {
- size += repeated_field_->SpaceUsedExcludingSelf();
+ if (MapFieldBase::repeated_field_ != NULL) {
+ size += MapFieldBase::repeated_field_->SpaceUsedExcludingSelf();
}
Map<Key, T>* map = const_cast<MapField*>(this)->MutableInternalMap();
size += sizeof(*map);
for (typename Map<Key, T>::iterator it = map->begin();
it != map->end(); ++it) {
- size += KeyHandler::SpaceUsedInMap(it->first);
- size += ValHandler::SpaceUsedInMap(it->second);
+ size += KeyTypeHandler::SpaceUsedInMap(it->first);
+ size += ValueTypeHandler::SpaceUsedInMap(it->second);
}
return size;
}
@@ -289,10 +467,11 @@ MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::InitDefaultEntryOnce()
const {
if (default_entry_ == NULL) {
- InitMetadataOnce();
- GOOGLE_CHECK(*entry_descriptor_ != NULL);
+ MapFieldBase::InitMetadataOnce();
+ GOOGLE_CHECK(*MapFieldBase::entry_descriptor_ != NULL);
default_entry_ = down_cast<const EntryType*>(
- MessageFactory::generated_factory()->GetPrototype(*entry_descriptor_));
+ MessageFactory::generated_factory()->GetPrototype(
+ *MapFieldBase::entry_descriptor_));
}
}
diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc
index e3a64079..2ff1d6bb 100644
--- a/src/google/protobuf/map_field_test.cc
+++ b/src/google/protobuf/map_field_test.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/arena.h>
#include <google/protobuf/map.h>
@@ -74,6 +75,28 @@ class MapFieldBaseStub : public MapFieldBase {
bool IsRepeatedClean() { return state_ != 1; }
void SetMapDirty() { state_ = 0; }
void SetRepeatedDirty() { state_ = 1; }
+ bool ContainsMapKey(const MapKey& map_key) const {
+ return false;
+ }
+ bool InsertMapValue(const MapKey& map_key, MapValueRef* val) {
+ return false;
+ }
+ bool DeleteMapValue(const MapKey& map_key) {
+ return false;
+ }
+ bool EqualIterator(const MapIterator& a, const MapIterator& b) const {
+ return false;
+ }
+ int size() const { return 0; }
+ void MapBegin(MapIterator* map_iter) const {}
+ void MapEnd(MapIterator* map_iter) const {}
+ void InitializeIterator(MapIterator* map_iter) const {}
+ void DeleteIterator(MapIterator* map_iter) const {}
+ void CopyIterator(MapIterator* this_iterator,
+ const MapIterator& other_iterator) const {}
+ void IncreaseIterator(MapIterator* map_iter) const {}
+ void SetDefaultMessageEntry(const Message* message) const {}
+ const Message* GetDefaultMessageEntry() const { return NULL; }
};
class MapFieldBasePrimitiveTest : public ::testing::Test {
diff --git a/src/google/protobuf/map_lite_unittest.proto b/src/google/protobuf/map_lite_unittest.proto
index c69e8d94..0592dd7a 100644
--- a/src/google/protobuf/map_lite_unittest.proto
+++ b/src/google/protobuf/map_lite_unittest.proto
@@ -34,6 +34,7 @@ option cc_enable_arenas = true;
option optimize_for = LITE_RUNTIME;
import "google/protobuf/unittest_lite.proto";
+import "google/protobuf/unittest_no_arena_lite.proto";
package protobuf_unittest;
@@ -72,8 +73,12 @@ message TestArenaMapLite {
map<int32 , float > map_int32_float = 11;
map<int32 , double > map_int32_double = 12;
map<bool , bool > map_bool_bool = 13;
- map<int32 , MapEnumLite> map_int32_enum = 14;
- map<int32 , ForeignMessageArenaLite> map_int32_foreign_message = 15;
+ map<string , string > map_string_string = 14;
+ map<int32 , bytes > map_int32_bytes = 15;
+ map<int32 , MapEnumLite> map_int32_enum = 16;
+ map<int32 , ForeignMessageArenaLite> map_int32_foreign_message = 17;
+ map<int32, .protobuf_unittest_no_arena.ForeignMessageLite>
+ map_int32_foreign_message_no_arena = 18;
}
// Test embeded message with required fields
@@ -81,10 +86,6 @@ message TestRequiredMessageMapLite {
map<int32, TestRequiredLite> map_field = 1;
}
-message TestEnumStartWithNonZeroMapLite {
- map<int32, Proto2MapEnumStartWithNonZeroLite> map_field = 101;
-}
-
message TestEnumMapLite {
map<int32, Proto2MapEnumLite> known_map_field = 101;
map<int32, Proto2MapEnumLite> unknown_map_field = 102;
@@ -112,10 +113,6 @@ enum Proto2MapEnumPlusExtraLite {
E_PROTO2_MAP_ENUM_EXTRA_LITE = 3;
}
-enum Proto2MapEnumStartWithNonZeroLite {
- PROTO2_NON_ZERO_MAP_ENUM_FOO_LITE = 1;
-}
-
enum MapEnumLite {
MAP_ENUM_FOO_LITE = 0;
MAP_ENUM_BAR_LITE = 1;
diff --git a/src/google/protobuf/map_proto2_unittest.proto b/src/google/protobuf/map_proto2_unittest.proto
index 3d4af28e..6f9d6165 100644
--- a/src/google/protobuf/map_proto2_unittest.proto
+++ b/src/google/protobuf/map_proto2_unittest.proto
@@ -49,10 +49,6 @@ enum Proto2MapEnumPlusExtra {
E_PROTO2_MAP_ENUM_EXTRA = 3;
}
-enum Proto2MapEnumStartWithNonZero {
- PROTO2_NON_ZERO_MAP_ENUM_FOO = 1;
-}
-
message TestEnumMap {
map<int32, Proto2MapEnum> known_map_field = 101;
map<int32, Proto2MapEnum> unknown_map_field = 102;
@@ -62,7 +58,3 @@ message TestEnumMapPlusExtra {
map<int32, Proto2MapEnumPlusExtra> known_map_field = 101;
map<int32, Proto2MapEnumPlusExtra> unknown_map_field = 102;
}
-
-message TestEnumStartWithNonZeroMap {
- map<int32, Proto2MapEnumStartWithNonZero> map_field = 101;
-}
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index d62ec85f..16a24c25 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -36,7 +36,9 @@
#include <sstream>
#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/arena_test_util.h>
@@ -70,6 +72,7 @@ namespace google {
using google::protobuf::unittest::ForeignMessage;
using google::protobuf::unittest::TestAllTypes;
using google::protobuf::unittest::TestMap;
+using google::protobuf::unittest::TestRecursiveMapMessage;
namespace protobuf {
namespace internal {
@@ -200,6 +203,21 @@ TEST_F(MapImplTest, ImmutableAtNonExistDeathTest) {
EXPECT_DEATH(const_map_.at(0), "");
}
+TEST_F(MapImplTest, UsageErrors) {
+ MapKey key;
+ key.SetInt64Value(1);
+ EXPECT_DEATH(key.GetUInt64Value(),
+ "Protocol Buffer map usage error:\n"
+ "MapKey::GetUInt64Value type does not match\n"
+ " Expected : uint64\n"
+ " Actual : int64");
+
+ MapValueRef value;
+ EXPECT_DEATH(value.SetFloatValue(0.1),
+ "Protocol Buffer map usage error:\n"
+ "MapValueRef::type MapValueRef is not initialized.");
+}
+
#endif // PROTOBUF_HAS_DEATH_TEST
TEST_F(MapImplTest, CountNonExist) {
@@ -475,6 +493,23 @@ TEST_F(MapImplTest, CopyConstructor) {
EXPECT_EQ(value2, other.at(key2));
}
+TEST_F(MapImplTest, IterConstructor) {
+ int32 key1 = 0;
+ int32 key2 = 1;
+ int32 value1 = 100;
+ int32 value2 = 101;
+
+ std::map<int32, int32> map;
+ map[key1] = value1;
+ map[key2] = value2;
+
+ Map<int32, int32> new_map(map.begin(), map.end());
+
+ EXPECT_EQ(2, new_map.size());
+ EXPECT_EQ(value1, new_map.at(key1));
+ EXPECT_EQ(value2, new_map.at(key2));
+}
+
TEST_F(MapImplTest, Assigner) {
int32 key1 = 0;
int32 key2 = 1;
@@ -1140,6 +1175,19 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) {
mmf_int32_foreign_message.Add(*entry_int32_foreign_message);
EXPECT_EQ(1234, message.map_int32_foreign_message().at(4321).c());
+ // Test Reflection::AddAllocatedMessage
+ Message* free_entry_string_string = MessageFactory::generated_factory()
+ ->GetPrototype(fd_map_string_string->message_type())
+ ->New();
+ entry_string_string->GetReflection()->SetString(
+ free_entry_string_string,
+ fd_map_string_string->message_type()->field(0), "4321");
+ entry_string_string->GetReflection()->SetString(
+ free_entry_string_string, fd_map_string_string->message_type()->field(1),
+ "1234");
+ refl->AddAllocatedMessage(&message, fd_map_string_string,
+ free_entry_string_string);
+
// Test MutableRepeatedFieldRef::RemoveLast()
mmf_int32_int32.RemoveLast();
mmf_int32_double.RemoveLast();
@@ -1147,7 +1195,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) {
mmf_int32_foreign_message.RemoveLast();
EXPECT_EQ(10, message.map_int32_int32().size());
EXPECT_EQ(10, message.map_int32_double().size());
- EXPECT_EQ(10, message.map_string_string().size());
+ EXPECT_EQ(11, message.map_string_string().size());
EXPECT_EQ(10, message.map_int32_foreign_message().size());
// Test MutableRepeatedFieldRef::SwapElements()
@@ -1398,9 +1446,9 @@ TEST(GeneratedMapFieldTest, SetMapFieldsInitialized) {
}
TEST(GeneratedMapFieldTest, Proto2SetMapFieldsInitialized) {
- unittest::TestEnumStartWithNonZeroMap message;
- EXPECT_EQ(unittest::PROTO2_NON_ZERO_MAP_ENUM_FOO,
- (*message.mutable_map_field())[0]);
+ unittest::TestEnumMap message;
+ EXPECT_EQ(unittest::PROTO2_MAP_ENUM_FOO,
+ (*message.mutable_known_map_field())[0]);
}
TEST(GeneratedMapFieldTest, Clear) {
@@ -1526,12 +1574,28 @@ TEST(GeneratedMapFieldTest, CopyFromDynamicMessage) {
google::protobuf::scoped_ptr<Message> message1;
message1.reset(
factory.GetPrototype(unittest::TestMap::descriptor())->New());
-
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
reflection_tester.SetMapFieldsViaReflection(message1.get());
reflection_tester.ExpectMapFieldsSetViaReflection(*message1);
+ reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get());
+ message2.CopyFrom(*message1);
+ MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(GeneratedMapFieldTest, CopyFromDynamicMessageMapReflection) {
+ unittest::TestMap message2;
+ // Construct a new version of the dynamic message via the factory.
+ DynamicMessageFactory factory;
+ google::protobuf::scoped_ptr<Message> message1;
+ message1.reset(
+ factory.GetPrototype(unittest::TestMap::descriptor())->New());
+ MapReflectionTester reflection_tester(
+ unittest::TestMap::descriptor());
+ reflection_tester.SetMapFieldsViaMapReflection(message1.get());
+ reflection_tester.ExpectMapFieldsSetViaReflection(*message1);
+ reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get());
message2.CopyFrom(*message1);
MapTestUtil::ExpectMapFieldsSet(message2);
}
@@ -1547,12 +1611,43 @@ TEST(GeneratedMapFieldTest, DynamicMessageCopyFrom) {
message1.reset(
factory.GetPrototype(unittest::TestMap::descriptor())->New());
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
+ unittest::TestMap::descriptor());
+ message1->MergeFrom(message2);
+ reflection_tester.ExpectMapFieldsSetViaReflection(*message1);
+ reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get());
+}
+
+TEST(GeneratedMapFieldTest, DynamicMessageCopyFromMapReflection) {
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
+ unittest::TestMap message2;
+ reflection_tester.SetMapFieldsViaMapReflection(&message2);
+
+ // Construct a dynamic message via the factory.
+ DynamicMessageFactory factory;
+ google::protobuf::scoped_ptr<Message> message1;
+ message1.reset(
+ factory.GetPrototype(unittest::TestMap::descriptor())->New());
+
message1->MergeFrom(message2);
+ reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get());
reflection_tester.ExpectMapFieldsSetViaReflection(*message1);
}
+TEST(GeneratedMapFieldTest, SyncDynamicMapWithRepeatedField) {
+ // Construct a dynamic message via the factory.
+ MapReflectionTester reflection_tester(
+ unittest::TestMap::descriptor());
+ DynamicMessageFactory factory;
+ google::protobuf::scoped_ptr<Message> message;
+ message.reset(
+ factory.GetPrototype(unittest::TestMap::descriptor())->New());
+ reflection_tester.SetMapFieldsViaReflection(message.get());
+ reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message.get());
+ reflection_tester.ExpectMapFieldsSetViaReflection(*message);
+}
+
#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
TEST(GeneratedMapFieldTest, NonEmptyMergeFrom) {
@@ -1779,7 +1874,7 @@ TEST(GeneratedMapFieldTest, IsInitialized) {
TEST(GeneratedMapFieldReflectionTest, SpaceUsed) {
unittest::TestMap message;
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
reflection_tester.SetMapFieldsViaReflection(&message);
@@ -1790,11 +1885,12 @@ TEST(GeneratedMapFieldReflectionTest, Accessors) {
// Set every field to a unique value then go back and check all those
// values.
unittest::TestMap message;
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
reflection_tester.SetMapFieldsViaReflection(&message);
MapTestUtil::ExpectMapFieldsSet(message);
reflection_tester.ExpectMapFieldsSetViaReflection(message);
+ reflection_tester.ExpectMapFieldsSetViaReflectionIterator(&message);
reflection_tester.ModifyMapFieldsViaReflection(&message);
MapTestUtil::ExpectMapFieldsModified(message);
@@ -1848,15 +1944,16 @@ TEST(GeneratedMapFieldReflectionTest, ClearField) {
MapTestUtil::SetMapFields(&message);
MapTestUtil::ExpectMapFieldsSet(message);
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
reflection_tester.ClearMapFieldsViaReflection(&message);
- MapTestUtil::ExpectClear(message);
+ reflection_tester.ExpectClearViaReflection(message);
+ reflection_tester.ExpectClearViaReflectionIterator(&message);
}
TEST(GeneratedMapFieldReflectionTest, RemoveLast) {
unittest::TestMap message;
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
MapTestUtil::SetMapFields(&message);
@@ -1875,7 +1972,7 @@ TEST(GeneratedMapFieldReflectionTest, RemoveLast) {
TEST(GeneratedMapFieldReflectionTest, ReleaseLast) {
unittest::TestMap message;
const Descriptor* descriptor = message.GetDescriptor();
- MapTestUtil::MapReflectionTester reflection_tester(descriptor);
+ MapReflectionTester reflection_tester(descriptor);
MapTestUtil::SetMapFields(&message);
@@ -1904,7 +2001,7 @@ TEST(GeneratedMapFieldReflectionTest, ReleaseLast) {
TEST(GeneratedMapFieldReflectionTest, SwapElements) {
unittest::TestMap message;
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
MapTestUtil::SetMapFields(&message);
@@ -1944,7 +2041,7 @@ TEST(GeneratedMapFieldReflectionTest, SwapElements) {
TEST(GeneratedMapFieldReflectionTest, MutableUnknownFields) {
unittest::TestMap message;
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
reflection_tester.MutableUnknownFieldsOfMapFieldsViaReflection(&message);
}
@@ -2000,24 +2097,35 @@ TEST(GeneratedMapFieldReflectionTest, MergeFromClearMapEntry) {
TEST(GeneratedMapFieldReflectionTest, MapEntryClear) {
unittest::TestMap message;
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
reflection_tester.MutableUnknownFieldsOfMapFieldsViaReflection(&message);
}
TEST(GeneratedMapFieldReflectionTest, Proto2MapEntryClear) {
- unittest::TestEnumStartWithNonZeroMap message;
+ unittest::TestEnumMap message;
const Descriptor* descriptor = message.GetDescriptor();
const FieldDescriptor* field_descriptor =
- descriptor->FindFieldByName("map_field");
+ descriptor->FindFieldByName("known_map_field");
const FieldDescriptor* value_descriptor =
field_descriptor->message_type()->FindFieldByName("value");
Message* sub_message =
message.GetReflection()->AddMessage(&message, field_descriptor);
- EXPECT_EQ(1, sub_message->GetReflection()->GetEnumValue(*sub_message,
+ EXPECT_EQ(0, sub_message->GetReflection()->GetEnumValue(*sub_message,
value_descriptor));
}
+// Map Reflection API Test =========================================
+
+TEST(GeneratedMapFieldReflectionTest, SetViaMapReflection) {
+ unittest::TestMap message;
+ MapReflectionTester reflection_tester(
+ unittest::TestMap::descriptor());
+ reflection_tester.SetMapFieldsViaMapReflection(&message);
+ reflection_tester.ExpectMapFieldsSetViaReflection(message);
+ reflection_tester.ExpectMapFieldsSetViaReflectionIterator(&message);
+}
+
// Dynamic Message Test =============================================
class MapFieldInDynamicMessageTest : public testing::Test {
@@ -2025,6 +2133,7 @@ class MapFieldInDynamicMessageTest : public testing::Test {
const DescriptorPool* pool_;
DynamicMessageFactory factory_;
const Descriptor* map_descriptor_;
+ const Descriptor* recursive_map_descriptor_;
const Message* map_prototype_;
MapFieldInDynamicMessageTest()
@@ -2033,7 +2142,10 @@ class MapFieldInDynamicMessageTest : public testing::Test {
virtual void SetUp() {
map_descriptor_ =
pool_->FindMessageTypeByName("protobuf_unittest.TestMap");
+ recursive_map_descriptor_ =
+ pool_->FindMessageTypeByName("protobuf_unittest.TestRecursiveMapMessage");
ASSERT_TRUE(map_descriptor_ != NULL);
+ ASSERT_TRUE(recursive_map_descriptor_ != NULL);
map_prototype_ = factory_.GetPrototype(map_descriptor_);
}
};
@@ -2043,19 +2155,19 @@ TEST_F(MapFieldInDynamicMessageTest, MapIndependentOffsets) {
// one to a unique value then checking that they all still have those
// unique values (i.e. they don't stomp each other).
scoped_ptr<Message> message(map_prototype_->New());
- MapTestUtil::MapReflectionTester reflection_tester(map_descriptor_);
+ MapReflectionTester reflection_tester(map_descriptor_);
reflection_tester.SetMapFieldsViaReflection(message.get());
reflection_tester.ExpectMapFieldsSetViaReflection(*message);
}
-TEST_F(MapFieldInDynamicMessageTest, Map) {
+TEST_F(MapFieldInDynamicMessageTest, DynamicMapReflection) {
// Check that map fields work properly.
scoped_ptr<Message> message(map_prototype_->New());
// Check set functions.
- MapTestUtil::MapReflectionTester reflection_tester(map_descriptor_);
- reflection_tester.SetMapFieldsViaReflection(message.get());
+ MapReflectionTester reflection_tester(map_descriptor_);
+ reflection_tester.SetMapFieldsViaMapReflection(message.get());
reflection_tester.ExpectMapFieldsSetViaReflection(*message);
}
@@ -2066,7 +2178,7 @@ TEST_F(MapFieldInDynamicMessageTest, MapSpaceUsed) {
// to test very much here. Just make sure it appears to be working.
scoped_ptr<Message> message(map_prototype_->New());
- MapTestUtil::MapReflectionTester reflection_tester(map_descriptor_);
+ MapReflectionTester reflection_tester(map_descriptor_);
int initial_space_used = message->SpaceUsed();
@@ -2074,6 +2186,15 @@ TEST_F(MapFieldInDynamicMessageTest, MapSpaceUsed) {
EXPECT_LT(initial_space_used, message->SpaceUsed());
}
+TEST_F(MapFieldInDynamicMessageTest, RecursiveMap) {
+ TestRecursiveMapMessage from;
+ (*from.mutable_a())[""];
+ string data = from.SerializeAsString();
+ google::protobuf::scoped_ptr<Message> to(
+ factory_.GetPrototype(recursive_map_descriptor_)->New());
+ ASSERT_TRUE(to->ParseFromString(data));
+}
+
// ReflectionOps Test ===============================================
TEST(ReflectionOpsForMapFieldTest, MapSanityCheck) {
@@ -2260,7 +2381,7 @@ TEST(TextFormatMapTest, SerializeAndParse) {
TEST(TextFormatMapTest, Sorted) {
unittest::TestMap message;
- MapTestUtil::MapReflectionTester tester(message.GetDescriptor());
+ MapReflectionTester tester(message.GetDescriptor());
tester.SetMapFieldsViaReflection(&message);
string expected_text;
@@ -2292,7 +2413,8 @@ TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) {
data.reserve(128 * 1024);
{
- NoHeapChecker no_heap;
+ // TODO(teboring): Enable no heap check when ArenaStringPtr is used in map.
+ // NoHeapChecker no_heap;
unittest::TestArenaMap* from =
Arena::CreateMessage<unittest::TestArenaMap>(&arena);
@@ -2326,6 +2448,22 @@ TEST(ArenaTest, RelfectionInTextFormat) {
MapTestUtil::ExpectArenaMapFieldsSet(*to);
}
+// Make sure the memory allocated for string in map is deallocated.
+TEST(ArenaTest, StringMapNoLeak) {
+ Arena arena;
+ unittest::TestArenaMap* message =
+ Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+ string data;
+ // String with length less than 16 will not be allocated from heap.
+ int original_capacity = data.capacity();
+ while (data.capacity() <= original_capacity) {
+ data.append("a");
+ }
+ (*message->mutable_map_string_string())[data] = data;
+ // We rely on heap checkers to detect memory leak for us.
+ ASSERT_FALSE(message == NULL);
+}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/map_test_util.cc b/src/google/protobuf/map_test_util.cc
index 1713e373..ae094647 100644
--- a/src/google/protobuf/map_test_util.cc
+++ b/src/google/protobuf/map_test_util.cc
@@ -209,7 +209,7 @@ std::vector<const Message*> MapTestUtil::GetMapEntriesFromRelease(
return result;
}
-MapTestUtil::MapReflectionTester::MapReflectionTester(
+MapReflectionTester::MapReflectionTester(
const Descriptor* base_descriptor)
: base_descriptor_(base_descriptor) {
const DescriptorPool* pool = base_descriptor->file()->pool();
@@ -329,14 +329,14 @@ MapTestUtil::MapReflectionTester::MapReflectionTester(
}
// Shorthand to get a FieldDescriptor for a field of unittest::TestMap.
-const FieldDescriptor* MapTestUtil::MapReflectionTester::F(const string& name) {
+const FieldDescriptor* MapReflectionTester::F(const string& name) {
const FieldDescriptor* result = NULL;
result = base_descriptor_->FindFieldByName(name);
GOOGLE_CHECK(result != NULL);
return result;
}
-void MapTestUtil::MapReflectionTester::SetMapFieldsViaReflection(
+void MapReflectionTester::SetMapFieldsViaReflection(
Message* message) {
const Reflection* reflection = message->GetReflection();
Message* sub_message = NULL;
@@ -555,7 +555,196 @@ void MapTestUtil::MapReflectionTester::SetMapFieldsViaReflection(
SetInt32(sub_foreign_message, foreign_c_, 1);
}
-void MapTestUtil::MapReflectionTester::ClearMapFieldsViaReflection(
+void MapReflectionTester::SetMapFieldsViaMapReflection(
+ Message* message) {
+ const Reflection* reflection = message->GetReflection();
+
+ Message* sub_foreign_message = NULL;
+ MapValueRef map_val;
+
+ // Add first element.
+ MapKey map_key;
+ map_key.SetInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_int32"), map_key, &map_val));
+ map_val.SetInt32Value(0);
+
+ map_key.SetInt64Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int64_int64"), map_key, &map_val));
+ map_val.SetInt64Value(0);
+
+ map_key.SetUInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_uint32_uint32"), map_key, &map_val));
+ map_val.SetUInt32Value(0);
+
+ map_key.SetUInt64Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_uint64_uint64"), map_key, &map_val));
+ map_val.SetUInt64Value(0);
+
+ map_key.SetInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_sint32_sint32"), map_key, &map_val));
+ map_val.SetInt32Value(0);
+
+ map_key.SetInt64Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_sint64_sint64"), map_key, &map_val));
+ map_val.SetInt64Value(0);
+
+ map_key.SetUInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_fixed32_fixed32"), map_key, &map_val));
+ map_val.SetUInt32Value(0);
+
+ map_key.SetUInt64Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_fixed64_fixed64"), map_key, &map_val));
+ map_val.SetUInt64Value(0);
+
+ map_key.SetInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_sfixed32_sfixed32"), map_key, &map_val));
+ map_val.SetInt32Value(0);
+
+ map_key.SetInt64Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_sfixed64_sfixed64"), map_key, &map_val));
+ map_val.SetInt64Value(0);
+
+ map_key.SetInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_float"), map_key, &map_val));
+ map_val.SetFloatValue(0.0);
+
+ map_key.SetInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_double"), map_key, &map_val));
+ map_val.SetDoubleValue(0.0);
+
+ map_key.SetBoolValue(false);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_bool_bool"), map_key, &map_val));
+ map_val.SetBoolValue(false);
+
+ map_key.SetStringValue("0");
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_string_string"), map_key, &map_val));
+ map_val.SetStringValue("0");
+
+ map_key.SetInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_bytes"), map_key, &map_val));
+ map_val.SetStringValue("0");
+
+ map_key.SetInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_enum"), map_key, &map_val));
+ map_val.SetEnumValue(map_enum_bar_->number());
+
+ map_key.SetInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_foreign_message"), map_key, &map_val));
+ sub_foreign_message = map_val.MutableMessageValue();
+ sub_foreign_message->GetReflection()->SetInt32(
+ sub_foreign_message, foreign_c_, 0);
+
+ // Add second element
+ map_key.SetInt32Value(1);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_int32"), map_key, &map_val));
+ map_val.SetInt32Value(1);
+ EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_int32"), map_key, &map_val));
+
+ map_key.SetInt64Value(1);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int64_int64"), map_key, &map_val));
+ map_val.SetInt64Value(1);
+ EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+ message, F("map_int64_int64"), map_key, &map_val));
+
+ map_key.SetUInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_uint32_uint32"), map_key, &map_val);
+ map_val.SetUInt32Value(1);
+
+ map_key.SetUInt64Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_uint64_uint64"), map_key, &map_val);
+ map_val.SetUInt64Value(1);
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_sint32_sint32"), map_key, &map_val);
+ map_val.SetInt32Value(1);
+
+ map_key.SetInt64Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_sint64_sint64"), map_key, &map_val);
+ map_val.SetInt64Value(1);
+
+ map_key.SetUInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_fixed32_fixed32"), map_key, &map_val);
+ map_val.SetUInt32Value(1);
+
+ map_key.SetUInt64Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_fixed64_fixed64"), map_key, &map_val);
+ map_val.SetUInt64Value(1);
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_sfixed32_sfixed32"), map_key, &map_val);
+ map_val.SetInt32Value(1);
+
+ map_key.SetInt64Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_sfixed64_sfixed64"), map_key, &map_val);
+ map_val.SetInt64Value(1);
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_int32_float"), map_key, &map_val);
+ map_val.SetFloatValue(1.0);
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_int32_double"), map_key, &map_val);
+ map_val.SetDoubleValue(1.0);
+
+ map_key.SetBoolValue(true);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_bool_bool"), map_key, &map_val);
+ map_val.SetBoolValue(true);
+
+ map_key.SetStringValue("1");
+ reflection->InsertOrLookupMapValue(
+ message, F("map_string_string"), map_key, &map_val);
+ map_val.SetStringValue("1");
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_int32_bytes"), map_key, &map_val);
+ map_val.SetStringValue("1");
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_int32_enum"), map_key, &map_val);
+ map_val.SetEnumValue(map_enum_baz_->number());
+
+ map_key.SetInt32Value(1);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_foreign_message"), map_key, &map_val));
+ sub_foreign_message = map_val.MutableMessageValue();
+ sub_foreign_message->GetReflection()->SetInt32(
+ sub_foreign_message, foreign_c_, 1);
+}
+
+void MapReflectionTester::ClearMapFieldsViaReflection(
Message* message) {
const Reflection* reflection = message->GetReflection();
@@ -578,97 +767,103 @@ void MapTestUtil::MapReflectionTester::ClearMapFieldsViaReflection(
reflection->ClearField(message, F("map_int32_foreign_message"));
}
-void MapTestUtil::MapReflectionTester::ModifyMapFieldsViaReflection(
+void MapReflectionTester::ModifyMapFieldsViaReflection(
Message* message) {
const Reflection* reflection = message->GetReflection();
- Message* sub_message;
+ MapValueRef map_val;
Message* sub_foreign_message;
- // Find out which one's key is 0.
- int size = reflection->FieldSize(*message, F("map_int32_int32"));
- int target = 0;
- for (int i = 0; i < size; i++) {
- const Message& temp_message = reflection
- ->GetRepeatedMessage(*message, F("map_int32_int32"), i);
- if (temp_message.GetReflection()
- ->GetInt32(temp_message, map_int32_int32_key_) == 1) {
- target = i;
- }
- }
-
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_int32_int32"), target);
- sub_message->GetReflection()
- ->SetInt32(sub_message, map_int32_int32_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_int64_int64"), target);
- sub_message->GetReflection()
- ->SetInt64(sub_message, map_int64_int64_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_uint32_uint32"), target);
- sub_message->GetReflection()
- ->SetUInt32(sub_message, map_uint32_uint32_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_uint64_uint64"), target);
- sub_message->GetReflection()
- ->SetUInt64(sub_message, map_uint64_uint64_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_sint32_sint32"), target);
- sub_message->GetReflection()
- ->SetInt32(sub_message, map_sint32_sint32_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_sint64_sint64"), target);
- sub_message->GetReflection()
- ->SetInt64(sub_message, map_sint64_sint64_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_fixed32_fixed32"), target);
- sub_message->GetReflection()
- ->SetUInt32(sub_message, map_fixed32_fixed32_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_fixed64_fixed64"), target);
- sub_message->GetReflection()
- ->SetUInt64(sub_message, map_fixed64_fixed64_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_sfixed32_sfixed32"), target);
- sub_message->GetReflection()
- ->SetInt32(sub_message, map_sfixed32_sfixed32_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_sfixed64_sfixed64"), target);
- sub_message->GetReflection()
- ->SetInt64(sub_message, map_sfixed64_sfixed64_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_int32_float"), target);
- sub_message->GetReflection()
- ->SetFloat(sub_message, map_int32_float_val_, 2.0);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_int32_double"), target);
- sub_message->GetReflection()
- ->SetDouble(sub_message, map_int32_double_val_, 2.0);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_bool_bool"), target);
- sub_message->GetReflection()
- ->SetBool(sub_message, map_bool_bool_val_, false);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_string_string"), target);
- sub_message->GetReflection()
- ->SetString(sub_message, map_string_string_val_, "2");
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_int32_bytes"), target);
- sub_message->GetReflection()
- ->SetString(sub_message, map_int32_bytes_val_, "2");
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_int32_enum"), target);
- sub_message->GetReflection()
- ->SetEnum(sub_message, map_int32_enum_val_, map_enum_foo_);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_int32_foreign_message"), target);
- sub_foreign_message = sub_message->GetReflection()->
- MutableMessage(sub_message, map_int32_foreign_message_val_, NULL);
- sub_foreign_message->GetReflection()->
- SetInt32(sub_foreign_message, foreign_c_, 2);
+ // Modify the second element
+ MapKey map_key;
+ map_key.SetInt32Value(1);
+ EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_int32"), map_key, &map_val));
+ map_val.SetInt32Value(2);
+
+ map_key.SetInt64Value(1);
+ EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+ message, F("map_int64_int64"), map_key, &map_val));
+ map_val.SetInt64Value(2);
+
+ map_key.SetUInt32Value(1);
+ EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+ message, F("map_uint32_uint32"), map_key, &map_val));
+ map_val.SetUInt32Value(2);
+
+ map_key.SetUInt64Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_uint64_uint64"), map_key, &map_val);
+ map_val.SetUInt64Value(2);
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_sint32_sint32"), map_key, &map_val);
+ map_val.SetInt32Value(2);
+
+ map_key.SetInt64Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_sint64_sint64"), map_key, &map_val);
+ map_val.SetInt64Value(2);
+
+ map_key.SetUInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_fixed32_fixed32"), map_key, &map_val);
+ map_val.SetUInt32Value(2);
+
+ map_key.SetUInt64Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_fixed64_fixed64"), map_key, &map_val);
+ map_val.SetUInt64Value(2);
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_sfixed32_sfixed32"), map_key, &map_val);
+ map_val.SetInt32Value(2);
+
+ map_key.SetInt64Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_sfixed64_sfixed64"), map_key, &map_val);
+ map_val.SetInt64Value(2);
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_int32_float"), map_key, &map_val);
+ map_val.SetFloatValue(2.0);
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_int32_double"), map_key, &map_val);
+ map_val.SetDoubleValue(2.0);
+
+ map_key.SetBoolValue(true);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_bool_bool"), map_key, &map_val);
+ map_val.SetBoolValue(false);
+
+ map_key.SetStringValue("1");
+ reflection->InsertOrLookupMapValue(
+ message, F("map_string_string"), map_key, &map_val);
+ map_val.SetStringValue("2");
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_int32_bytes"), map_key, &map_val);
+ map_val.SetStringValue("2");
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_int32_enum"), map_key, &map_val);
+ map_val.SetEnumValue(map_enum_foo_->number());
+
+ map_key.SetInt32Value(1);
+ EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_foreign_message"), map_key, &map_val));
+ sub_foreign_message = map_val.MutableMessageValue();
+ sub_foreign_message->GetReflection()->SetInt32(
+ sub_foreign_message, foreign_c_, 2);
}
-void MapTestUtil::MapReflectionTester::RemoveLastMapsViaReflection(
+void MapReflectionTester::RemoveLastMapsViaReflection(
Message* message) {
const Reflection* reflection = message->GetReflection();
@@ -681,7 +876,7 @@ void MapTestUtil::MapReflectionTester::RemoveLastMapsViaReflection(
}
}
-void MapTestUtil::MapReflectionTester::ReleaseLastMapsViaReflection(
+void MapReflectionTester::ReleaseLastMapsViaReflection(
Message* message) {
const Reflection* reflection = message->GetReflection();
@@ -699,7 +894,7 @@ void MapTestUtil::MapReflectionTester::ReleaseLastMapsViaReflection(
}
}
-void MapTestUtil::MapReflectionTester::SwapMapsViaReflection(Message* message) {
+void MapReflectionTester::SwapMapsViaReflection(Message* message) {
const Reflection* reflection = message->GetReflection();
vector<const FieldDescriptor*> output;
reflection->ListFields(*message, &output);
@@ -710,7 +905,7 @@ void MapTestUtil::MapReflectionTester::SwapMapsViaReflection(Message* message) {
}
}
-void MapTestUtil::MapReflectionTester::
+void MapReflectionTester::
MutableUnknownFieldsOfMapFieldsViaReflection(Message* message) {
const Reflection* reflection = message->GetReflection();
Message* sub_message = NULL;
@@ -768,11 +963,12 @@ void MapTestUtil::MapReflectionTester::
NULL);
}
-void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
+void MapReflectionTester::ExpectMapFieldsSetViaReflection(
const Message& message) {
string scratch;
const Reflection* reflection = message.GetReflection();
const Message* sub_message;
+ MapKey map_key;
// -----------------------------------------------------------------
@@ -799,6 +995,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
map[0] = 0;
map[1] = 1;
for (int i = 0; i < 2; i++) {
+ // Check with RepeatedField Reflection
sub_message =
&reflection->GetRepeatedMessage(message, F("map_int32_int32"), i);
int32 key = sub_message->GetReflection()->GetInt32(
@@ -806,6 +1003,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
int32 val = sub_message->GetReflection()->GetInt32(
*sub_message, map_int32_int32_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt32Value(key);
+ EXPECT_TRUE(reflection->ContainsMapKey(
+ message, F("map_int32_int32"), map_key));
}
}
{
@@ -813,6 +1014,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
map[0] = 0;
map[1] = 1;
for (int i = 0; i < 2; i++) {
+ // Check with RepeatedField Reflection
sub_message =
&reflection->GetRepeatedMessage(message, F("map_int64_int64"), i);
int64 key = sub_message->GetReflection()->GetInt64(
@@ -820,6 +1022,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
int64 val = sub_message->GetReflection()->GetInt64(
*sub_message, map_int64_int64_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt64Value(key);
+ EXPECT_TRUE(reflection->ContainsMapKey(
+ message, F("map_int64_int64"), map_key));
}
}
{
@@ -827,6 +1033,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
map[0] = 0;
map[1] = 1;
for (int i = 0; i < 2; i++) {
+ // Check with RepeatedField Reflection
sub_message =
&reflection->GetRepeatedMessage(message, F("map_uint32_uint32"), i);
uint32 key = sub_message->GetReflection()->GetUInt32(
@@ -834,6 +1041,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
uint32 val = sub_message->GetReflection()->GetUInt32(
*sub_message, map_uint32_uint32_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetUInt32Value(key);
+ EXPECT_TRUE(reflection->ContainsMapKey(
+ message, F("map_uint32_uint32"), map_key));
}
}
{
@@ -848,6 +1059,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
uint64 val = sub_message->GetReflection()->GetUInt64(
*sub_message, map_uint64_uint64_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetUInt64Value(key);
+ EXPECT_TRUE(reflection->ContainsMapKey(
+ message, F("map_uint64_uint64"), map_key));
}
}
{
@@ -862,6 +1077,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
int32 val = sub_message->GetReflection()->GetInt32(
*sub_message, map_sint32_sint32_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt32Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_sint32_sint32"), map_key));
}
}
{
@@ -876,6 +1095,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
int64 val = sub_message->GetReflection()->GetInt64(
*sub_message, map_sint64_sint64_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt64Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_sint64_sint64"), map_key));
}
}
{
@@ -890,6 +1113,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
uint32 val = sub_message->GetReflection()->GetUInt32(
*sub_message, map_fixed32_fixed32_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetUInt32Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_fixed32_fixed32"), map_key));
}
}
{
@@ -904,6 +1131,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
uint64 val = sub_message->GetReflection()->GetUInt64(
*sub_message, map_fixed64_fixed64_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetUInt64Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_fixed64_fixed64"), map_key));
}
}
{
@@ -918,6 +1149,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
int32 val = sub_message->GetReflection()->GetInt32(
*sub_message, map_sfixed32_sfixed32_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt32Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_sfixed32_sfixed32"), map_key));
}
}
{
@@ -932,6 +1167,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
int64 val = sub_message->GetReflection()->GetInt64(
*sub_message, map_sfixed64_sfixed64_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt64Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_sfixed64_sfixed64"), map_key));
}
}
{
@@ -946,6 +1185,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
float val = sub_message->GetReflection()->GetFloat(
*sub_message, map_int32_float_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt32Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_int32_float"), map_key));
}
}
{
@@ -960,6 +1203,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
double val = sub_message->GetReflection()->GetDouble(
*sub_message, map_int32_double_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt32Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_int32_double"), map_key));
}
}
{
@@ -974,6 +1221,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
bool val = sub_message->GetReflection()->GetBool(
*sub_message, map_bool_bool_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetBoolValue(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_bool_bool"), map_key));
}
}
{
@@ -988,6 +1239,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
string val = sub_message->GetReflection()->GetString(
*sub_message, map_string_string_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetStringValue(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_string_string"), map_key));
}
}
{
@@ -1002,6 +1257,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
string val = sub_message->GetReflection()->GetString(
*sub_message, map_int32_bytes_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt32Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_int32_bytes"), map_key));
}
}
{
@@ -1016,6 +1275,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
const EnumValueDescriptor* val = sub_message->GetReflection()->GetEnum(
*sub_message, map_int32_enum_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt32Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_int32_enum"), map_key));
}
}
{
@@ -1032,11 +1295,245 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
int32 val = foreign_message.GetReflection()->GetInt32(
foreign_message, foreign_c_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt32Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_int32_foreign_message"), map_key));
}
}
}
-void MapTestUtil::MapReflectionTester::ExpectClearViaReflection(
+void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
+ Message* message) {
+ string scratch;
+ string serialized;
+ const Reflection* reflection = message->GetReflection();
+
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_int32")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int64_int64")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_uint32_uint32")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_uint64_uint64")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sint32_sint32")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sint64_sint64")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_fixed32_fixed32")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_fixed64_fixed64")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sfixed32_sfixed32")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sfixed64_sfixed64")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_float")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_double")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_bool_bool")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_string_string")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_bytes")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_enum")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_foreign_message")));
+
+ {
+ std::map<int32, int32> map;
+ map[0] = 0;
+ map[1] = 1;
+ int size = 0;
+ for (MapIterator iter = reflection->MapBegin(message, F("map_int32_int32"));
+ iter != reflection->MapEnd(message, F("map_int32_int32"));
+ ++iter, ++size) {
+ // Check const methods do not invalidate map.
+ message->DebugString();
+ message->ShortDebugString();
+ message->SerializeToString(&serialized);
+ message->SpaceUsed();
+ message->ByteSize();
+ EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+ iter.GetValueRef().GetInt32Value());
+ }
+ EXPECT_EQ(size, 2);
+ }
+ {
+ std::map<int64, int64> map;
+ map[0] = 0;
+ map[1] = 1;
+ for (MapIterator iter = reflection->MapBegin(message, F("map_int64_int64"));
+ iter != reflection->MapEnd(message, F("map_int64_int64")); ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetInt64Value()],
+ iter.GetValueRef().GetInt64Value());
+ }
+ }
+ {
+ std::map<uint32, uint32> map;
+ map[0] = 0;
+ map[1] = 1;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_uint32_uint32"));
+ iter != reflection->MapEnd(message, F("map_uint32_uint32"));
+ ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetUInt32Value()],
+ iter.GetValueRef().GetUInt32Value());
+ }
+ }
+ {
+ std::map<uint64, uint64> map;
+ map[0] = 0;
+ map[1] = 1;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_uint64_uint64"));
+ iter != reflection->MapEnd(message, F("map_uint64_uint64"));
+ ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetUInt64Value()],
+ iter.GetValueRef().GetUInt64Value());
+ }
+ }
+ {
+ std::map<int32, int32> map;
+ map[0] = 0;
+ map[1] = 1;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_sint32_sint32"));
+ iter != reflection->MapEnd(message, F("map_sint32_sint32"));
+ ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+ iter.GetValueRef().GetInt32Value());
+ }
+ }
+ {
+ std::map<int64, int64> map;
+ map[0] = 0;
+ map[1] = 1;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_sint64_sint64"));
+ iter != reflection->MapEnd(message, F("map_sint64_sint64")); ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetInt64Value()],
+ iter.GetValueRef().GetInt64Value());
+ }
+ }
+ {
+ std::map<uint32, uint32> map;
+ map[0] = 0;
+ map[1] = 1;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_fixed32_fixed32"));
+ iter != reflection->MapEnd(message, F("map_fixed32_fixed32"));
+ ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetUInt32Value()],
+ iter.GetValueRef().GetUInt32Value());
+ }
+ }
+ {
+ std::map<uint64, uint64> map;
+ map[0] = 0;
+ map[1] = 1;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_fixed64_fixed64"));
+ iter != reflection->MapEnd(message, F("map_fixed64_fixed64"));
+ ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetUInt64Value()],
+ iter.GetValueRef().GetUInt64Value());
+ }
+ }
+ {
+ std::map<int32, int32> map;
+ map[0] = 0;
+ map[1] = 1;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_sfixed32_sfixed32"));
+ iter != reflection->MapEnd(message, F("map_sfixed32_sfixed32"));
+ ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+ iter.GetValueRef().GetInt32Value());
+ }
+ }
+ {
+ std::map<int32, float> map;
+ map[0] = 0.0;
+ map[1] = 1.0;
+ for (MapIterator iter = reflection->MapBegin(message, F("map_int32_float"));
+ iter != reflection->MapEnd(message, F("map_int32_float")); ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+ iter.GetValueRef().GetFloatValue());
+ }
+ }
+ {
+ std::map<int32, double> map;
+ map[0] = 0.0;
+ map[1] = 1.0;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_int32_double"));
+ iter != reflection->MapEnd(message, F("map_int32_double")); ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+ iter.GetValueRef().GetDoubleValue());
+ }
+ }
+ {
+ std::map<bool, bool> map;
+ map[false] = false;
+ map[true] = true;
+ for (MapIterator iter = reflection->MapBegin(message, F("map_bool_bool"));
+ iter != reflection->MapEnd(message, F("map_bool_bool")); ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetBoolValue()],
+ iter.GetValueRef().GetBoolValue());
+ }
+ }
+ {
+ std::map<string, string> map;
+ map["0"] = "0";
+ map["1"] = "1";
+ int size = 0;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_string_string"));
+ iter != reflection->MapEnd(message, F("map_string_string"));
+ ++iter, ++size) {
+ // Check const methods do not invalidate map.
+ message->DebugString();
+ message->ShortDebugString();
+ message->SerializeToString(&serialized);
+ message->SpaceUsed();
+ message->ByteSize();
+ EXPECT_EQ(map[iter.GetKey().GetStringValue()],
+ iter.GetValueRef().GetStringValue());
+ }
+ EXPECT_EQ(size, 2);
+ }
+ {
+ std::map<int32, string> map;
+ map[0] = "0";
+ map[1] = "1";
+ for (MapIterator iter = reflection->MapBegin(message, F("map_int32_bytes"));
+ iter != reflection->MapEnd(message, F("map_int32_bytes")); ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+ iter.GetValueRef().GetStringValue());
+ }
+ }
+ {
+ std::map<int32, const EnumValueDescriptor*> map;
+ map[0] = map_enum_bar_;
+ map[1] = map_enum_baz_;
+ for (MapIterator iter = reflection->MapBegin(message, F("map_int32_enum"));
+ iter != reflection->MapEnd(message, F("map_int32_enum")); ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetInt32Value()]->number(),
+ iter.GetValueRef().GetEnumValue());
+ }
+ }
+ {
+ std::map<int32, int32> map;
+ map[0] = 0;
+ map[1] = 1;
+ int size = 0;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_int32_foreign_message"));
+ iter != reflection->MapEnd(message, F("map_int32_foreign_message"));
+ ++iter, ++size) {
+ // Check const methods do not invalidate map.
+ message->DebugString();
+ message->ShortDebugString();
+ message->SerializeToString(&serialized);
+ message->SpaceUsed();
+ message->ByteSize();
+ const Message& sub_message = iter.GetValueRef().GetMessageValue();
+ EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+ sub_message.GetReflection()->GetInt32(sub_message, foreign_c_));
+ }
+ EXPECT_EQ(size, 2);
+ }
+}
+
+void MapReflectionTester::ExpectClearViaReflection(
const Message& message) {
const Reflection* reflection = message.GetReflection();
// Map fields are empty.
@@ -1059,7 +1556,46 @@ void MapTestUtil::MapReflectionTester::ExpectClearViaReflection(
EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_foreign_message")));
}
-void MapTestUtil::MapReflectionTester::ExpectMapEntryClearViaReflection(
+void MapReflectionTester::ExpectClearViaReflectionIterator(
+ Message* message) {
+ const Reflection* reflection = message->GetReflection();
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_int32")) ==
+ reflection->MapEnd(message, F("map_int32_int32")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_int64_int64")) ==
+ reflection->MapEnd(message, F("map_int64_int64")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_uint32_uint32")) ==
+ reflection->MapEnd(message, F("map_uint32_uint32")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_uint64_uint64")) ==
+ reflection->MapEnd(message, F("map_uint64_uint64")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_sint32_sint32")) ==
+ reflection->MapEnd(message, F("map_sint32_sint32")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_sint64_sint64")) ==
+ reflection->MapEnd(message, F("map_sint64_sint64")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_fixed32_fixed32")) ==
+ reflection->MapEnd(message, F("map_fixed32_fixed32")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_fixed64_fixed64")) ==
+ reflection->MapEnd(message, F("map_fixed64_fixed64")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_sfixed32_sfixed32")) ==
+ reflection->MapEnd(message, F("map_sfixed32_sfixed32")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_sfixed64_sfixed64")) ==
+ reflection->MapEnd(message, F("map_sfixed64_sfixed64")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_float")) ==
+ reflection->MapEnd(message, F("map_int32_float")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_double")) ==
+ reflection->MapEnd(message, F("map_int32_double")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_bool_bool")) ==
+ reflection->MapEnd(message, F("map_bool_bool")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_string_string")) ==
+ reflection->MapEnd(message, F("map_string_string")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_bytes")) ==
+ reflection->MapEnd(message, F("map_int32_bytes")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_enum")) ==
+ reflection->MapEnd(message, F("map_int32_enum")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_foreign_message")) ==
+ reflection->MapEnd(message, F("map_int32_foreign_message")));
+}
+
+void MapReflectionTester::ExpectMapEntryClearViaReflection(
Message* message) {
const Reflection* reflection = message->GetReflection();
const Message* sub_message;
diff --git a/src/google/protobuf/map_test_util.h b/src/google/protobuf/map_test_util.h
index f437e33e..107a639d 100644
--- a/src/google/protobuf/map_test_util.h
+++ b/src/google/protobuf/map_test_util.h
@@ -83,71 +83,74 @@ class MapTestUtil {
// Get pointers of map entries from release.
static std::vector<const Message*> GetMapEntriesFromRelease(
unittest::TestMap* message);
+};
- // Like above, but use the reflection interface.
- class MapReflectionTester {
- public:
- // base_descriptor must be a descriptor for TestMap, which is used for
- // MapReflectionTester to fetch the FieldDescriptors needed to use the
- // reflection interface.
- explicit MapReflectionTester(const Descriptor* base_descriptor);
-
- void SetMapFieldsViaReflection(Message* message);
- void ClearMapFieldsViaReflection(Message* message);
- void ModifyMapFieldsViaReflection(Message* message);
- void RemoveLastMapsViaReflection(Message* message);
- void ReleaseLastMapsViaReflection(Message* message);
- void SwapMapsViaReflection(Message* message);
- void MutableUnknownFieldsOfMapFieldsViaReflection(Message* message);
- void ExpectMapFieldsSetViaReflection(const Message& message);
- void ExpectClearViaReflection(const Message& message);
- void ExpectMapEntryClearViaReflection(Message* message);
-
- private:
- const FieldDescriptor* F(const string& name);
-
- const Descriptor* base_descriptor_;
-
- const EnumValueDescriptor* map_enum_bar_;
- const EnumValueDescriptor* map_enum_baz_;
- const EnumValueDescriptor* map_enum_foo_;
-
- const FieldDescriptor* foreign_c_;
- const FieldDescriptor* map_int32_int32_key_;
- const FieldDescriptor* map_int32_int32_val_;
- const FieldDescriptor* map_int64_int64_key_;
- const FieldDescriptor* map_int64_int64_val_;
- const FieldDescriptor* map_uint32_uint32_key_;
- const FieldDescriptor* map_uint32_uint32_val_;
- const FieldDescriptor* map_uint64_uint64_key_;
- const FieldDescriptor* map_uint64_uint64_val_;
- const FieldDescriptor* map_sint32_sint32_key_;
- const FieldDescriptor* map_sint32_sint32_val_;
- const FieldDescriptor* map_sint64_sint64_key_;
- const FieldDescriptor* map_sint64_sint64_val_;
- const FieldDescriptor* map_fixed32_fixed32_key_;
- const FieldDescriptor* map_fixed32_fixed32_val_;
- const FieldDescriptor* map_fixed64_fixed64_key_;
- const FieldDescriptor* map_fixed64_fixed64_val_;
- const FieldDescriptor* map_sfixed32_sfixed32_key_;
- const FieldDescriptor* map_sfixed32_sfixed32_val_;
- const FieldDescriptor* map_sfixed64_sfixed64_key_;
- const FieldDescriptor* map_sfixed64_sfixed64_val_;
- const FieldDescriptor* map_int32_float_key_;
- const FieldDescriptor* map_int32_float_val_;
- const FieldDescriptor* map_int32_double_key_;
- const FieldDescriptor* map_int32_double_val_;
- const FieldDescriptor* map_bool_bool_key_;
- const FieldDescriptor* map_bool_bool_val_;
- const FieldDescriptor* map_string_string_key_;
- const FieldDescriptor* map_string_string_val_;
- const FieldDescriptor* map_int32_bytes_key_;
- const FieldDescriptor* map_int32_bytes_val_;
- const FieldDescriptor* map_int32_enum_key_;
- const FieldDescriptor* map_int32_enum_val_;
- const FieldDescriptor* map_int32_foreign_message_key_;
- const FieldDescriptor* map_int32_foreign_message_val_;
- };
+// Like above, but use the reflection interface.
+class MapReflectionTester {
+ public:
+ // base_descriptor must be a descriptor for TestMap, which is used for
+ // MapReflectionTester to fetch the FieldDescriptors needed to use the
+ // reflection interface.
+ explicit MapReflectionTester(const Descriptor* base_descriptor);
+
+ void SetMapFieldsViaReflection(Message* message);
+ void SetMapFieldsViaMapReflection(Message* message);
+ void ClearMapFieldsViaReflection(Message* message);
+ void ModifyMapFieldsViaReflection(Message* message);
+ void RemoveLastMapsViaReflection(Message* message);
+ void ReleaseLastMapsViaReflection(Message* message);
+ void SwapMapsViaReflection(Message* message);
+ void MutableUnknownFieldsOfMapFieldsViaReflection(Message* message);
+ void ExpectMapFieldsSetViaReflection(const Message& message);
+ void ExpectMapFieldsSetViaReflectionIterator(Message* message);
+ void ExpectClearViaReflection(const Message& message);
+ void ExpectClearViaReflectionIterator(Message* message);
+ void ExpectMapEntryClearViaReflection(Message* message);
+
+ private:
+ const FieldDescriptor* F(const string& name);
+
+ const Descriptor* base_descriptor_;
+
+ const EnumValueDescriptor* map_enum_bar_;
+ const EnumValueDescriptor* map_enum_baz_;
+ const EnumValueDescriptor* map_enum_foo_;
+
+ const FieldDescriptor* foreign_c_;
+ const FieldDescriptor* map_int32_int32_key_;
+ const FieldDescriptor* map_int32_int32_val_;
+ const FieldDescriptor* map_int64_int64_key_;
+ const FieldDescriptor* map_int64_int64_val_;
+ const FieldDescriptor* map_uint32_uint32_key_;
+ const FieldDescriptor* map_uint32_uint32_val_;
+ const FieldDescriptor* map_uint64_uint64_key_;
+ const FieldDescriptor* map_uint64_uint64_val_;
+ const FieldDescriptor* map_sint32_sint32_key_;
+ const FieldDescriptor* map_sint32_sint32_val_;
+ const FieldDescriptor* map_sint64_sint64_key_;
+ const FieldDescriptor* map_sint64_sint64_val_;
+ const FieldDescriptor* map_fixed32_fixed32_key_;
+ const FieldDescriptor* map_fixed32_fixed32_val_;
+ const FieldDescriptor* map_fixed64_fixed64_key_;
+ const FieldDescriptor* map_fixed64_fixed64_val_;
+ const FieldDescriptor* map_sfixed32_sfixed32_key_;
+ const FieldDescriptor* map_sfixed32_sfixed32_val_;
+ const FieldDescriptor* map_sfixed64_sfixed64_key_;
+ const FieldDescriptor* map_sfixed64_sfixed64_val_;
+ const FieldDescriptor* map_int32_float_key_;
+ const FieldDescriptor* map_int32_float_val_;
+ const FieldDescriptor* map_int32_double_key_;
+ const FieldDescriptor* map_int32_double_val_;
+ const FieldDescriptor* map_bool_bool_key_;
+ const FieldDescriptor* map_bool_bool_val_;
+ const FieldDescriptor* map_string_string_key_;
+ const FieldDescriptor* map_string_string_val_;
+ const FieldDescriptor* map_int32_bytes_key_;
+ const FieldDescriptor* map_int32_bytes_val_;
+ const FieldDescriptor* map_int32_enum_key_;
+ const FieldDescriptor* map_int32_enum_val_;
+ const FieldDescriptor* map_int32_foreign_message_key_;
+ const FieldDescriptor* map_int32_foreign_message_val_;
};
} // namespace protobuf
diff --git a/src/google/protobuf/map_test_util_impl.h b/src/google/protobuf/map_test_util_impl.h
index 5e7882a1..7e8757ed 100644
--- a/src/google/protobuf/map_test_util_impl.h
+++ b/src/google/protobuf/map_test_util_impl.h
@@ -31,6 +31,7 @@
#ifndef GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__
#define GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
@@ -167,8 +168,11 @@ void MapTestUtilImpl::SetArenaMapFields(MapMessage* message) {
(*message->mutable_map_int32_float())[0] = 0.0;
(*message->mutable_map_int32_double())[0] = 0.0;
(*message->mutable_map_bool_bool())[0] = false;
+ (*message->mutable_map_string_string())["0"] = "0";
+ (*message->mutable_map_int32_bytes())[0] = "0";
(*message->mutable_map_int32_enum())[0] = enum_value0;
(*message->mutable_map_int32_foreign_message())[0].set_c(0);
+ (*message->mutable_map_int32_foreign_message_no_arena())[0].set_c(0);
// Add second element
(*message->mutable_map_int32_int32())[1] = 1;
@@ -184,8 +188,11 @@ void MapTestUtilImpl::SetArenaMapFields(MapMessage* message) {
(*message->mutable_map_int32_float())[1] = 1.0;
(*message->mutable_map_int32_double())[1] = 1.0;
(*message->mutable_map_bool_bool())[1] = true;
+ (*message->mutable_map_string_string())["1"] = "1";
+ (*message->mutable_map_int32_bytes())[1] = "1";
(*message->mutable_map_int32_enum())[1] = enum_value1;
(*message->mutable_map_int32_foreign_message())[1].set_c(1);
+ (*message->mutable_map_int32_foreign_message_no_arena())[1].set_c(1);
}
template <typename MapMessage>
@@ -329,8 +336,11 @@ void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) {
EXPECT_EQ(2, message.map_int32_float().size());
EXPECT_EQ(2, message.map_int32_double().size());
EXPECT_EQ(2, message.map_bool_bool().size());
+ EXPECT_EQ(2, message.map_string_string().size());
+ EXPECT_EQ(2, message.map_int32_bytes().size());
EXPECT_EQ(2, message.map_int32_enum().size());
EXPECT_EQ(2, message.map_int32_foreign_message().size());
+ EXPECT_EQ(2, message.map_int32_foreign_message_no_arena().size());
EXPECT_EQ(0, message.map_int32_int32().at(0));
EXPECT_EQ(0, message.map_int64_int64().at(0));
@@ -345,8 +355,11 @@ void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) {
EXPECT_EQ(0, message.map_int32_float().at(0));
EXPECT_EQ(0, message.map_int32_double().at(0));
EXPECT_EQ(false, message.map_bool_bool().at(0));
+ EXPECT_EQ("0", message.map_string_string().at("0"));
+ EXPECT_EQ("0", message.map_int32_bytes().at(0));
EXPECT_EQ(enum_value0, message.map_int32_enum().at(0));
EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
+ EXPECT_EQ(0, message.map_int32_foreign_message_no_arena().at(0).c());
EXPECT_EQ(1, message.map_int32_int32().at(1));
EXPECT_EQ(1, message.map_int64_int64().at(1));
@@ -361,8 +374,11 @@ void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) {
EXPECT_EQ(1, message.map_int32_float().at(1));
EXPECT_EQ(1, message.map_int32_double().at(1));
EXPECT_EQ(true, message.map_bool_bool().at(1));
+ EXPECT_EQ("1", message.map_string_string().at("1"));
+ EXPECT_EQ("1", message.map_int32_bytes().at(1));
EXPECT_EQ(enum_value1, message.map_int32_enum().at(1));
EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c());
+ EXPECT_EQ(1, message.map_int32_foreign_message_no_arena().at(1).c());
}
template <typename EnumType, EnumType enum_value, typename MapMessage>
diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h
index ffdb6dfb..f8ad7584 100644
--- a/src/google/protobuf/map_type_handler.h
+++ b/src/google/protobuf/map_type_handler.h
@@ -54,22 +54,6 @@ struct MapIf<false, TrueType, FalseType> {
typedef FalseType type;
};
-// In MapField, string and message are stored as pointer while others are stored
-// as object. However, google::protobuf::Map has unified api. Functions in this class
-// convert key/value to type wanted in api regardless how it's stored
-// internally.
-template <typename Type>
-class MapCommonTypeHandler {
- public:
- static inline Type& Reference(Type* x) { return *x; }
- static inline Type& Reference(Type& x) { return x; }
- static inline const Type& Reference(const Type& x) { return x; }
- static inline Type* Pointer(Type* x) { return x; }
- static inline Type* Pointer(Type& x) { return &x; }
- static inline const Type* Pointer(const Type* x) { return x; }
- static inline const Type* Pointer(const Type& x) { return &x; }
-};
-
// In proto2 Map, enum needs to be initialized to given default value, while
// other types' default value can be inferred from the type.
template <bool IsEnum, typename Type>
@@ -110,174 +94,29 @@ template <typename Type>
class MapArenaMessageCreator<Type, false> {
public:
static inline Type* CreateMessage(Arena* arena) {
- return new Type;
- }
-};
-
-// Handlers for key/value stored type in MapField. ==================
-
-// Handler for message
-template <typename Type>
-class MapCppTypeHandler : public MapCommonTypeHandler<Type> {
- public:
- static const bool kIsStringOrMessage = true;
- // SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding
- // those already calculate in sizeof(MapField).
- static int SpaceUsedInMapEntry(const Type* value) {
- return value->SpaceUsed();
- }
- // Return bytes used by value in Map.
- static int SpaceUsedInMap(const Type& value) { return value.SpaceUsed(); }
- static inline void Clear(Type** value) {
- if (*value != NULL) (*value)->Clear();
- }
- static inline void ClearMaybeByDefaultEnum(Type** value,
- int default_enum_value) {
- if (*value != NULL) (*value)->Clear();
- }
- static inline void Merge(const Type& from, Type** to) {
- (*to)->MergeFrom(from);
- }
-
- static void Delete(const Type* ptr) { delete ptr; }
-
- // Assign default value to given instance.
- static inline void AssignDefaultValue(Type** value) {
- *value = const_cast<Type*>(&Type::default_instance());
- }
- // Initialize value when constructing MapEntry
- static inline void Initialize(Type** x, Arena* arena) { *x = NULL; }
- // Same as above, but use default_enum_value to initialize enum type value.
- static inline void InitializeMaybeByDefaultEnum(
- Type** x, int default_enum_value, Arena* arena) {
- *x = NULL;
- }
- // Initialize value for the first time mutable accessor is called.
- static inline void EnsureMutable(Type** value, Arena* arena) {
- if (*value == NULL) {
- *value =
- MapArenaMessageCreator<Type, Arena::is_arena_constructable<Type>::
- type::value>::CreateMessage(arena);
- }
- }
- // Return default instance if value is not initialized when calling const
- // reference accessor.
- static inline const Type& DefaultIfNotInitialized(const Type* value,
- const Type* default_value) {
- return value != NULL ? *value : *default_value;
- }
- // Check if all required fields have values set.
- static inline bool IsInitialized(Type* value) {
- return value->IsInitialized();
- }
-};
-
-// Handler for string.
-template <>
-class MapCppTypeHandler<string> : public MapCommonTypeHandler<string> {
- public:
- static const bool kIsStringOrMessage = true;
- static inline void Merge(const string& from, string** to) { **to = from; }
- static inline void Clear(string** value) { (*value)->clear(); }
- static inline void ClearMaybeByDefaultEnum(string** value, int default_enum) {
- (*value)->clear();
- }
- static inline int SpaceUsedInMapEntry(const string* value) {
- return sizeof(*value) + StringSpaceUsedExcludingSelf(*value);
- }
- static inline int SpaceUsedInMap(const string& value) {
- return sizeof(value) + StringSpaceUsedExcludingSelf(value);
- }
- static void Delete(const string* ptr) {
- if (ptr != &::google::protobuf::internal::GetEmptyString()) delete ptr;
- }
- static inline void AssignDefaultValue(string** value) {}
- static inline void Initialize(string** value, Arena* arena) {
- *value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
- if (arena != NULL) arena->Own(*value);
- }
- static inline void InitializeMaybeByDefaultEnum(
- string** value, int default_enum_value, Arena* arena) {
- *value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
- if (arena != NULL) arena->Own(*value);
+ return Arena::Create<Type>(arena);
}
- static inline void EnsureMutable(string** value, Arena* arena) {
- if (*value == &::google::protobuf::internal::GetEmptyString()) {
- *value = Arena::Create<string>(arena);
- }
- }
- static inline const string& DefaultIfNotInitialized(
- const string* value,
- const string* default_value) {
- return value != default_value ? *value : *default_value;
- }
- static inline bool IsInitialized(string* value) { return true; }
};
-// Base class for primitive type handlers.
-template <typename Type>
-class MapPrimitiveTypeHandler : public MapCommonTypeHandler<Type> {
- public:
- static const bool kIsStringOrMessage = false;
- static inline void Delete(const Type& x) {}
- static inline void Merge(const Type& from, Type* to) { *to = from; }
- static inline int SpaceUsedInMapEntry(const Type& value) { return 0; }
- static inline int SpaceUsedInMap(const Type& value) { return sizeof(Type); }
- static inline void AssignDefaultValue(Type* value) {}
- static inline const Type& DefaultIfNotInitialized(
- const Type& value, const Type& default_value) {
- return value;
- }
- static inline bool IsInitialized(const Type& value) { return true; }
-};
-
-// Handlers for primitive types.
-#define PRIMITIVE_HANDLER(CType) \
- template <> \
- class MapCppTypeHandler<CType> : public MapPrimitiveTypeHandler<CType> { \
- public: \
- static inline void Clear(CType* value) { *value = 0; } \
- static inline void ClearMaybeByDefaultEnum(CType* value, \
- int default_enum_value) { \
- *value = static_cast<CType>(default_enum_value); \
- } \
- static inline void Initialize(CType* value, Arena* arena) { *value = 0; } \
- static inline void InitializeMaybeByDefaultEnum(CType* value, \
- int default_enum_value, \
- Arena* arena) { \
- *value = static_cast<CType>(default_enum_value); \
- } \
- static inline void EnsureMutable(CType* value, Arena* arena) {} \
- };
-
-PRIMITIVE_HANDLER(int32 )
-PRIMITIVE_HANDLER(int64 )
-PRIMITIVE_HANDLER(uint32)
-PRIMITIVE_HANDLER(uint64)
-PRIMITIVE_HANDLER(double)
-PRIMITIVE_HANDLER(float )
-PRIMITIVE_HANDLER(bool )
-
-#undef PRIMITIVE_HANDLER
-
// Define constants for given wire field type
-template <WireFormatLite::FieldType field_type>
+template <WireFormatLite::FieldType field_type, typename Type>
class MapWireFieldTypeTraits {};
-#define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \
- template <> \
- class MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType> { \
- public: \
- typedef CType CppType; \
- static const bool kIsMessage = IsMessage; \
- static const bool kIsEnum = IsEnum; \
- static const WireFormatLite::WireType kWireType = \
- WireFormatLite::WIRETYPE_##WireFormatType; \
+#define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \
+ template <typename Type> \
+ class MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, Type> { \
+ public: \
+ static const bool kIsMessage = IsMessage; \
+ static const bool kIsEnum = IsEnum; \
+ typedef typename MapIf<kIsMessage, Type*, CType>::type TypeOnMemory; \
+ typedef typename MapIf<kIsEnum, int, Type>::type MapEntryAccessorType; \
+ static const WireFormatLite::WireType kWireType = \
+ WireFormatLite::WIRETYPE_##WireFormatType; \
};
-TYPE_TRAITS(MESSAGE , MessageLite, LENGTH_DELIMITED, true, false)
-TYPE_TRAITS(STRING , string , LENGTH_DELIMITED, false, false)
-TYPE_TRAITS(BYTES , string , LENGTH_DELIMITED, false, false)
+TYPE_TRAITS(MESSAGE , Type, LENGTH_DELIMITED, true, false)
+TYPE_TRAITS(STRING , ArenaStringPtr, LENGTH_DELIMITED, false, false)
+TYPE_TRAITS(BYTES , ArenaStringPtr , LENGTH_DELIMITED, false, false)
TYPE_TRAITS(INT64 , int64 , VARINT , false, false)
TYPE_TRAITS(UINT64 , uint64 , VARINT , false, false)
TYPE_TRAITS(INT32 , int32 , VARINT , false, false)
@@ -295,67 +134,168 @@ TYPE_TRAITS(BOOL , bool , VARINT , false, false)
#undef TYPE_TRAITS
-template <WireFormatLite::FieldType field_type>
-class MapWireFieldTypeHandler {
+template <WireFormatLite::FieldType field_type, typename Type>
+class MapTypeHandler {};
+
+template <typename Type>
+class MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type> {
public:
+ // Enum type cannot be used for MapTypeHandler::Read. Define a type which will
+ // replace Enum with int.
+ typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE,
+ Type>::MapEntryAccessorType MapEntryAccessorType;
// Internal stored type in MapEntryLite for given wire field type.
- typedef typename MapWireFieldTypeTraits<field_type>::CppType CppType;
+ typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE,
+ Type>::TypeOnMemory TypeOnMemory;
// Corresponding wire type for field type.
static const WireFormatLite::WireType kWireType =
- MapWireFieldTypeTraits<field_type>::kWireType;
+ MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kWireType;
// Whether wire type is for message.
- static const bool kIsMessage = MapWireFieldTypeTraits<field_type>::kIsMessage;
+ static const bool kIsMessage =
+ MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kIsMessage;
// Whether wire type is for enum.
- static const bool kIsEnum = MapWireFieldTypeTraits<field_type>::kIsEnum;
+ static const bool kIsEnum =
+ MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kIsEnum;
// Functions used in parsing and serialization. ===================
- template <typename ValueType>
- static inline int ByteSize(const ValueType& value);
- template <typename ValueType>
- static inline int GetCachedSize(const ValueType& value);
- template <typename ValueType>
- static inline bool Read(io::CodedInputStream* input, ValueType* value);
- static inline void Write(int field, const CppType& value,
+ static inline int ByteSize(const MapEntryAccessorType& value);
+ static inline int GetCachedSize(const MapEntryAccessorType& value);
+ static inline bool Read(io::CodedInputStream* input,
+ MapEntryAccessorType* value);
+ static inline void Write(int field, const MapEntryAccessorType& value,
io::CodedOutputStream* output);
- static inline uint8* WriteToArray(int field, const CppType& value,
+ static inline uint8* WriteToArray(int field,
+ const MapEntryAccessorType& value,
uint8* output);
+
+ // Functions to manipulate data on memory. ========================
+ static inline const Type& GetExternalReference(const Type* value);
+ static inline void DeleteNoArena(const Type* x);
+ static inline void Merge(const Type& from, Type** to, Arena* arena);
+ static inline void Clear(Type** value, Arena* arena);
+ static inline void ClearMaybeByDefaultEnum(Type** value, Arena* arena,
+ int default_enum_value);
+ static inline void Initialize(Type** x, Arena* arena);
+
+ static inline void InitializeMaybeByDefaultEnum(Type** x,
+ int default_enum_value,
+ Arena* arena);
+ static inline Type* EnsureMutable(Type** value, Arena* arena);
+ // SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding
+ // those already calculate in sizeof(MapField).
+ static inline int SpaceUsedInMapEntry(const Type* value);
+ // Return bytes used by value in Map.
+ static inline int SpaceUsedInMap(const Type& value);
+ // Assign default value to given instance.
+ static inline void AssignDefaultValue(Type** value);
+ // Return default instance if value is not initialized when calling const
+ // reference accessor.
+ static inline const Type& DefaultIfNotInitialized(
+ const Type* value, const Type* default_value);
+ // Check if all required fields have values set.
+ static inline bool IsInitialized(Type* value);
};
-template <>
-template <typename ValueType>
-inline int MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::ByteSize(
- const ValueType& value) {
+#define MAP_HANDLER(FieldType) \
+ template <typename Type> \
+ class MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type> { \
+ public: \
+ typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
+ Type>::MapEntryAccessorType \
+ MapEntryAccessorType; \
+ typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
+ Type>::TypeOnMemory TypeOnMemory; \
+ static const WireFormatLite::WireType kWireType = \
+ MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
+ Type>::kWireType; \
+ static const bool kIsMessage = \
+ MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
+ Type>::kIsMessage; \
+ static const bool kIsEnum = \
+ MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
+ Type>::kIsEnum; \
+ static inline int ByteSize(const MapEntryAccessorType& value); \
+ static inline int GetCachedSize(const MapEntryAccessorType& value); \
+ static inline bool Read(io::CodedInputStream* input, \
+ MapEntryAccessorType* value); \
+ static inline void Write(int field, const MapEntryAccessorType& value, \
+ io::CodedOutputStream* output); \
+ static inline uint8* WriteToArray(int field, \
+ const MapEntryAccessorType& value, \
+ uint8* output); \
+ static inline const MapEntryAccessorType& GetExternalReference( \
+ const TypeOnMemory& value); \
+ static inline void DeleteNoArena(const TypeOnMemory& x); \
+ static inline void Merge(const MapEntryAccessorType& from, \
+ TypeOnMemory* to, Arena* arena); \
+ static inline void Clear(TypeOnMemory* value, Arena* arena); \
+ static inline void ClearMaybeByDefaultEnum(TypeOnMemory* value, \
+ Arena* arena, \
+ int default_enum); \
+ static inline int SpaceUsedInMapEntry(const TypeOnMemory& value); \
+ static inline int SpaceUsedInMap(const TypeOnMemory& value); \
+ static inline int SpaceUsedInMap(const string& value); \
+ static inline void AssignDefaultValue(TypeOnMemory* value); \
+ static inline const MapEntryAccessorType& DefaultIfNotInitialized( \
+ const TypeOnMemory& value, const TypeOnMemory& default_value); \
+ static inline bool IsInitialized(const TypeOnMemory& value); \
+ static void DeleteNoArena(TypeOnMemory& value); \
+ static inline void Initialize(TypeOnMemory* value, Arena* arena); \
+ static inline void InitializeMaybeByDefaultEnum(TypeOnMemory* value, \
+ int default_enum_value, \
+ Arena* arena); \
+ static inline MapEntryAccessorType* EnsureMutable(TypeOnMemory* value, \
+ Arena* arena); \
+ };
+MAP_HANDLER(STRING)
+MAP_HANDLER(BYTES)
+MAP_HANDLER(INT64)
+MAP_HANDLER(UINT64)
+MAP_HANDLER(INT32)
+MAP_HANDLER(UINT32)
+MAP_HANDLER(SINT64)
+MAP_HANDLER(SINT32)
+MAP_HANDLER(ENUM)
+MAP_HANDLER(DOUBLE)
+MAP_HANDLER(FLOAT)
+MAP_HANDLER(FIXED64)
+MAP_HANDLER(FIXED32)
+MAP_HANDLER(SFIXED64)
+MAP_HANDLER(SFIXED32)
+MAP_HANDLER(BOOL)
+#undef MAP_HANDLER
+
+template <typename Type>
+inline int
+MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::ByteSize(
+ const MapEntryAccessorType& value) {
return WireFormatLite::MessageSizeNoVirtual(value);
}
-#define BYTE_SIZE(FieldType, DeclaredType) \
- template <> \
- template <typename ValueType> \
- inline int \
- MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::ByteSize( \
- const ValueType& value) { \
- return WireFormatLite::DeclaredType##Size(value); \
+#define GOOGLE_PROTOBUF_BYTE_SIZE(FieldType, DeclaredType) \
+ template <typename Type> \
+ inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
+ const MapEntryAccessorType& value) { \
+ return WireFormatLite::DeclaredType##Size(value); \
}
-BYTE_SIZE(STRING, String)
-BYTE_SIZE(BYTES , Bytes)
-BYTE_SIZE(INT64 , Int64)
-BYTE_SIZE(UINT64, UInt64)
-BYTE_SIZE(INT32 , Int32)
-BYTE_SIZE(UINT32, UInt32)
-BYTE_SIZE(SINT64, SInt64)
-BYTE_SIZE(SINT32, SInt32)
-BYTE_SIZE(ENUM , Enum)
-
-#undef BYTE_SIZE
-
-#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \
- template <> \
- template <typename ValueType> \
- inline int \
- MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::ByteSize( \
- const ValueType& value) { \
- return WireFormatLite::k##DeclaredType##Size; \
+GOOGLE_PROTOBUF_BYTE_SIZE(STRING, String)
+GOOGLE_PROTOBUF_BYTE_SIZE(BYTES , Bytes)
+GOOGLE_PROTOBUF_BYTE_SIZE(INT64 , Int64)
+GOOGLE_PROTOBUF_BYTE_SIZE(UINT64, UInt64)
+GOOGLE_PROTOBUF_BYTE_SIZE(INT32 , Int32)
+GOOGLE_PROTOBUF_BYTE_SIZE(UINT32, UInt32)
+GOOGLE_PROTOBUF_BYTE_SIZE(SINT64, SInt64)
+GOOGLE_PROTOBUF_BYTE_SIZE(SINT32, SInt32)
+GOOGLE_PROTOBUF_BYTE_SIZE(ENUM , Enum)
+
+#undef GOOGLE_PROTOBUF_BYTE_SIZE
+
+#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \
+ template <typename Type> \
+ inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
+ const MapEntryAccessorType& value) { \
+ return WireFormatLite::k##DeclaredType##Size; \
}
FIXED_BYTE_SIZE(DOUBLE , Double)
@@ -368,20 +308,19 @@ FIXED_BYTE_SIZE(BOOL , Bool)
#undef FIXED_BYTE_SIZE
-template <>
-template <typename ValueType>
-inline int MapWireFieldTypeHandler<
- WireFormatLite::TYPE_MESSAGE>::GetCachedSize(const ValueType& value) {
+template <typename Type>
+inline int
+MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::GetCachedSize(
+ const MapEntryAccessorType& value) {
return WireFormatLite::LengthDelimitedSize(value.GetCachedSize());
}
-#define GET_CACHED_SIZE(FieldType, DeclaredType) \
- template <> \
- template <typename ValueType> \
- inline int \
- MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::GetCachedSize( \
- const ValueType& value) { \
- return WireFormatLite::DeclaredType##Size(value); \
+#define GET_CACHED_SIZE(FieldType, DeclaredType) \
+ template <typename Type> \
+ inline int \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
+ const MapEntryAccessorType& value) { \
+ return WireFormatLite::DeclaredType##Size(value); \
}
GET_CACHED_SIZE(STRING, String)
@@ -396,13 +335,12 @@ GET_CACHED_SIZE(ENUM , Enum)
#undef GET_CACHED_SIZE
-#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \
- template <> \
- template <typename ValueType> \
- inline int \
- MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::GetCachedSize( \
- const ValueType& value) { \
- return WireFormatLite::k##DeclaredType##Size; \
+#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \
+ template <typename Type> \
+ inline int \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
+ const MapEntryAccessorType& value) { \
+ return WireFormatLite::k##DeclaredType##Size; \
}
GET_FIXED_CACHED_SIZE(DOUBLE , Double)
@@ -415,30 +353,31 @@ GET_FIXED_CACHED_SIZE(BOOL , Bool)
#undef GET_FIXED_CACHED_SIZE
-template <>
-inline void MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::Write(
- int field, const MessageLite& value, io::CodedOutputStream* output) {
+template <typename Type>
+inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Write(
+ int field, const MapEntryAccessorType& value,
+ io::CodedOutputStream* output) {
WireFormatLite::WriteMessageMaybeToArray(field, value, output);
}
-template <>
+template <typename Type>
inline uint8*
-MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::WriteToArray(
- int field, const MessageLite& value, uint8* output) {
+MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::WriteToArray(
+ int field, const MapEntryAccessorType& value, uint8* output) {
return WireFormatLite::WriteMessageToArray(field, value, output);
}
#define WRITE_METHOD(FieldType, DeclaredType) \
- template <> \
- inline void \
- MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::Write( \
- int field, const CppType& value, io::CodedOutputStream* output) { \
+ template <typename Type> \
+ inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Write( \
+ int field, const MapEntryAccessorType& value, \
+ io::CodedOutputStream* output) { \
return WireFormatLite::Write##DeclaredType(field, value, output); \
} \
- template <> \
+ template <typename Type> \
inline uint8* \
- MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::WriteToArray( \
- int field, const CppType& value, uint8* output) { \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::WriteToArray( \
+ int field, const MapEntryAccessorType& value, uint8* output) { \
return WireFormatLite::Write##DeclaredType##ToArray(field, value, output); \
}
@@ -461,35 +400,31 @@ WRITE_METHOD(BOOL , Bool)
#undef WRITE_METHOD
-template <>
-template <typename ValueType>
-inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::Read(
- io::CodedInputStream* input, ValueType* value) {
+template <typename Type>
+inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Read(
+ io::CodedInputStream* input, MapEntryAccessorType* value) {
return WireFormatLite::ReadMessageNoVirtual(input, value);
}
-template <>
-template <typename ValueType>
-inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_STRING>::Read(
- io::CodedInputStream* input, ValueType* value) {
+template <typename Type>
+inline bool MapTypeHandler<WireFormatLite::TYPE_STRING, Type>::Read(
+ io::CodedInputStream* input, MapEntryAccessorType* value) {
return WireFormatLite::ReadString(input, value);
}
-template <>
-template <typename ValueType>
-inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_BYTES>::Read(
- io::CodedInputStream* input, ValueType* value) {
+template <typename Type>
+inline bool MapTypeHandler<WireFormatLite::TYPE_BYTES, Type>::Read(
+ io::CodedInputStream* input, MapEntryAccessorType* value) {
return WireFormatLite::ReadBytes(input, value);
}
-#define READ_METHOD(FieldType) \
- template <> \
- template <typename ValueType> \
- inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::Read( \
- io::CodedInputStream* input, ValueType* value) { \
- return WireFormatLite::ReadPrimitive<CppType, \
- WireFormatLite::TYPE_##FieldType>( \
- input, value); \
+#define READ_METHOD(FieldType) \
+ template <typename Type> \
+ inline bool MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Read( \
+ io::CodedInputStream* input, MapEntryAccessorType* value) { \
+ return WireFormatLite::ReadPrimitive<TypeOnMemory, \
+ WireFormatLite::TYPE_##FieldType>( \
+ input, value); \
}
READ_METHOD(INT64)
@@ -509,6 +444,282 @@ READ_METHOD(BOOL)
#undef READ_METHOD
+// Definition for message handler
+
+template <typename Type>
+inline const Type&
+MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
+ Type>::GetExternalReference(const Type* value) {
+ return *value;
+}
+
+template <typename Type>
+inline int
+MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
+ Type>::SpaceUsedInMapEntry(const Type* value) {
+ return value->SpaceUsed();
+}
+
+template <typename Type>
+int MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::SpaceUsedInMap(
+ const Type& value) {
+ return value.SpaceUsed();
+}
+
+template <typename Type>
+inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Clear(
+ Type** value, Arena* arena) {
+ if (*value != NULL) (*value)->Clear();
+}
+template <typename Type>
+inline void
+MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
+ Type>::ClearMaybeByDefaultEnum(Type** value,
+ Arena* arena,
+ int default_enum_value) {
+ if (*value != NULL) (*value)->Clear();
+}
+template <typename Type>
+inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Merge(
+ const Type& from, Type** to, Arena* arena) {
+ (*to)->MergeFrom(from);
+}
+
+template <typename Type>
+void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::DeleteNoArena(
+ const Type* ptr) {
+ delete ptr;
+}
+
+template <typename Type>
+inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
+ Type>::AssignDefaultValue(Type** value) {
+ *value = const_cast<Type*>(&Type::default_instance());
+}
+
+template <typename Type>
+inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
+ Type>::Initialize(Type** x,
+ Arena* arena) {
+ *x = NULL;
+}
+
+template <typename Type>
+inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::
+ InitializeMaybeByDefaultEnum(Type** x, int default_enum_value,
+ Arena* arena) {
+ *x = NULL;
+}
+
+template <typename Type>
+inline Type* MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
+ Type>::EnsureMutable(Type** value,
+ Arena* arena) {
+ if (*value == NULL) {
+ *value =
+ MapArenaMessageCreator<Type, Arena::is_arena_constructable<Type>::
+ type::value>::CreateMessage(arena);
+ }
+ return *value;
+}
+
+template <typename Type>
+inline const Type& MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::
+ DefaultIfNotInitialized(const Type* value, const Type* default_value) {
+ return value != NULL ? *value : *default_value;
+}
+
+template <typename Type>
+inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
+ Type>::IsInitialized(Type* value) {
+ return value->IsInitialized();
+}
+
+// Definition for string/bytes handler
+
+#define STRING_OR_BYTES_HANDLER_FUNCTIONS(FieldType) \
+ template <typename Type> \
+ inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::MapEntryAccessorType& \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::GetExternalReference(const TypeOnMemory& value) { \
+ return value.Get(&::google::protobuf::internal::GetEmptyString()); \
+ } \
+ template <typename Type> \
+ inline int \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::SpaceUsedInMapEntry( \
+ const TypeOnMemory& value) { \
+ return sizeof(value); \
+ } \
+ template <typename Type> \
+ inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::SpaceUsedInMap(const TypeOnMemory& value) { \
+ return sizeof(value); \
+ } \
+ template <typename Type> \
+ inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::SpaceUsedInMap(const string& value) { \
+ return sizeof(value); \
+ } \
+ template <typename Type> \
+ inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear( \
+ TypeOnMemory* value, Arena* arena) { \
+ value->ClearToEmpty(&::google::protobuf::internal::GetEmptyString(), arena); \
+ } \
+ template <typename Type> \
+ inline void \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::ClearMaybeByDefaultEnum(TypeOnMemory* value, \
+ Arena* arena, \
+ int default_enum) { \
+ Clear(value, arena); \
+ } \
+ template <typename Type> \
+ inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge( \
+ const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) { \
+ to->Set(&::google::protobuf::internal::GetEmptyString(), from, arena); \
+ } \
+ template <typename Type> \
+ void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::DeleteNoArena( \
+ TypeOnMemory& value) { \
+ value.DestroyNoArena(&::google::protobuf::internal::GetEmptyString()); \
+ } \
+ template <typename Type> \
+ inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::AssignDefaultValue(TypeOnMemory* value) {} \
+ template <typename Type> \
+ inline void \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Initialize( \
+ TypeOnMemory* value, Arena* arena) { \
+ value->UnsafeSetDefault(&::google::protobuf::internal::GetEmptyString()); \
+ } \
+ template <typename Type> \
+ inline void \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::InitializeMaybeByDefaultEnum(TypeOnMemory* value, \
+ int default_enum_value, \
+ Arena* arena) { \
+ Initialize(value, arena); \
+ } \
+ template <typename Type> \
+ inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::MapEntryAccessorType* \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable( \
+ TypeOnMemory* value, Arena* arena) { \
+ return value->Mutable(&::google::protobuf::internal::GetEmptyString(), arena); \
+ } \
+ template <typename Type> \
+ inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::MapEntryAccessorType& \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::DefaultIfNotInitialized(const TypeOnMemory& value, \
+ const TypeOnMemory& \
+ default_value) { \
+ return value.Get(&::google::protobuf::internal::GetEmptyString()); \
+ } \
+ template <typename Type> \
+ inline bool MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::IsInitialized(const TypeOnMemory& value) { \
+ return true; \
+ }
+STRING_OR_BYTES_HANDLER_FUNCTIONS(STRING)
+STRING_OR_BYTES_HANDLER_FUNCTIONS(BYTES)
+#undef STRING_OR_BYTES_HANDLER_FUNCTIONS
+
+#define PRIMITIVE_HANDLER_FUNCTIONS(FieldType) \
+ template <typename Type> \
+ inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::MapEntryAccessorType& \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::GetExternalReference(const TypeOnMemory& value) { \
+ return value; \
+ } \
+ template <typename Type> \
+ inline int \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::SpaceUsedInMapEntry( \
+ const TypeOnMemory& value) { \
+ return 0; \
+ } \
+ template <typename Type> \
+ inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::SpaceUsedInMap(const TypeOnMemory& value) { \
+ return sizeof(Type); \
+ } \
+ template <typename Type> \
+ inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear( \
+ TypeOnMemory* value, Arena* arena) { \
+ *value = 0; \
+ } \
+ template <typename Type> \
+ inline void \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::ClearMaybeByDefaultEnum(TypeOnMemory* value, \
+ Arena* arena, \
+ int default_enum_value) { \
+ *value = static_cast<TypeOnMemory>(default_enum_value); \
+ } \
+ template <typename Type> \
+ inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge( \
+ const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) { \
+ *to = from; \
+ } \
+ template <typename Type> \
+ inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::DeleteNoArena(TypeOnMemory& x) {} \
+ template <typename Type> \
+ inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::AssignDefaultValue(TypeOnMemory* value) {} \
+ template <typename Type> \
+ inline void \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Initialize( \
+ TypeOnMemory* value, Arena* arena) { \
+ *value = 0; \
+ } \
+ template <typename Type> \
+ inline void \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::InitializeMaybeByDefaultEnum(TypeOnMemory* value, \
+ int default_enum_value, \
+ Arena* arena) { \
+ *value = static_cast<TypeOnMemory>(default_enum_value); \
+ } \
+ template <typename Type> \
+ inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::MapEntryAccessorType* \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable( \
+ TypeOnMemory* value, Arena* arena) { \
+ return value; \
+ } \
+ template <typename Type> \
+ inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::MapEntryAccessorType& \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::DefaultIfNotInitialized(const TypeOnMemory& value, \
+ const TypeOnMemory& \
+ default_value) { \
+ return value; \
+ } \
+ template <typename Type> \
+ inline bool MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::IsInitialized(const TypeOnMemory& value) { \
+ return true; \
+ }
+PRIMITIVE_HANDLER_FUNCTIONS(INT64)
+PRIMITIVE_HANDLER_FUNCTIONS(UINT64)
+PRIMITIVE_HANDLER_FUNCTIONS(INT32)
+PRIMITIVE_HANDLER_FUNCTIONS(UINT32)
+PRIMITIVE_HANDLER_FUNCTIONS(SINT64)
+PRIMITIVE_HANDLER_FUNCTIONS(SINT32)
+PRIMITIVE_HANDLER_FUNCTIONS(ENUM)
+PRIMITIVE_HANDLER_FUNCTIONS(DOUBLE)
+PRIMITIVE_HANDLER_FUNCTIONS(FLOAT)
+PRIMITIVE_HANDLER_FUNCTIONS(FIXED64)
+PRIMITIVE_HANDLER_FUNCTIONS(FIXED32)
+PRIMITIVE_HANDLER_FUNCTIONS(SFIXED64)
+PRIMITIVE_HANDLER_FUNCTIONS(SFIXED32)
+PRIMITIVE_HANDLER_FUNCTIONS(BOOL)
+#undef PRIMITIVE_HANDLER_FUNCTIONS
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto
index b308c7ff..aea1e8ce 100644
--- a/src/google/protobuf/map_unittest.proto
+++ b/src/google/protobuf/map_unittest.proto
@@ -33,6 +33,7 @@ syntax = "proto3";
option cc_enable_arenas = true;
import "google/protobuf/unittest.proto";
+import "google/protobuf/unittest_no_arena.proto";
// We don't put this in a package within proto2 because we need to make sure
// that the generated code doesn't depend on being in the proto2 namespace.
@@ -58,6 +59,7 @@ message TestMap {
map<int32 , bytes > map_int32_bytes = 15;
map<int32 , MapEnum > map_int32_enum = 16;
map<int32 , ForeignMessage> map_int32_foreign_message = 17;
+ map<string , ForeignMessage> map_string_foreign_message = 18;
}
message TestMapSubmessage {
@@ -100,8 +102,12 @@ message TestArenaMap {
map<int32 , float > map_int32_float = 11;
map<int32 , double > map_int32_double = 12;
map<bool , bool > map_bool_bool = 13;
- map<int32 , MapEnum > map_int32_enum = 14;
- map<int32 , ForeignMessage> map_int32_foreign_message = 15;
+ map<string , string > map_string_string = 14;
+ map<int32 , bytes > map_int32_bytes = 15;
+ map<int32 , MapEnum > map_int32_enum = 16;
+ map<int32 , ForeignMessage> map_int32_foreign_message = 17;
+ map<int32, .protobuf_unittest_no_arena.ForeignMessage>
+ map_int32_foreign_message_no_arena = 18;
}
// Previously, message containing enum called Type cannot be used as value of
@@ -110,10 +116,14 @@ message MessageContainingEnumCalledType {
enum Type {
TYPE_FOO = 0;
}
- map<int32, MessageContainingEnumCalledType> type = 1;
+ map<string, MessageContainingEnumCalledType> type = 1;
}
// Previously, message cannot contain map field called "entry".
message MessageContainingMapCalledEntry {
map<int32, int32> entry = 1;
}
+
+message TestRecursiveMapMessage {
+ map<string, TestRecursiveMapMessage> a = 1;
+}
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index 123bd789..9a586783 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -38,12 +38,15 @@
#include <google/protobuf/message.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/mutex.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/reflection_internal.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/map_field.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/reflection_ops.h>
@@ -257,6 +260,22 @@ void Reflection::AddEnumValue(Message* message,
GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
}
+MapIterator Reflection::MapBegin(
+ Message* message,
+ const FieldDescriptor* field) const {
+ GOOGLE_LOG(FATAL) << "Unimplemented Map Reflection API.";
+ MapIterator iter(message, field);
+ return iter;
+}
+
+MapIterator Reflection::MapEnd(
+ Message* message,
+ const FieldDescriptor* field) const {
+ GOOGLE_LOG(FATAL) << "Unimplemented Map Reflection API.";
+ MapIterator iter(message, field);
+ return iter;
+}
+
// =============================================================================
// MessageFactory
@@ -476,11 +495,19 @@ Message* GenericTypeHandler<Message>::NewFromPrototype(
return prototype->New(arena);
}
template<>
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+// Note: force noinline to workaround MSVC 2015 compiler bug, issue #240
+GOOGLE_ATTRIBUTE_NOINLINE
+#endif
google::protobuf::Arena* GenericTypeHandler<Message>::GetArena(
Message* value) {
return value->GetArena();
}
template<>
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+// Note: force noinline to workaround MSVC 2015 compiler bug, issue #240
+GOOGLE_ATTRIBUTE_NOINLINE
+#endif
void* GenericTypeHandler<Message>::GetMaybeArenaPointer(
Message* value) {
return value->GetMaybeArenaPointer();
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index 18c092d0..348e7c7f 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -134,12 +134,23 @@ class Reflection;
class MessageFactory;
// Defined in other files.
+class MapKey;
+class MapValueRef;
+class MapIterator;
+class MapReflectionTester;
+
+namespace internal {
+class MapFieldBase;
+}
class UnknownFieldSet; // unknown_field_set.h
namespace io {
- class ZeroCopyInputStream; // zero_copy_stream.h
- class ZeroCopyOutputStream; // zero_copy_stream.h
- class CodedInputStream; // coded_stream.h
- class CodedOutputStream; // coded_stream.h
+class ZeroCopyInputStream; // zero_copy_stream.h
+class ZeroCopyOutputStream; // zero_copy_stream.h
+class CodedInputStream; // coded_stream.h
+class CodedOutputStream; // coded_stream.h
+}
+namespace python {
+class MapReflectionFriend; // scalar_map_container.h
}
@@ -724,6 +735,14 @@ class LIBPROTOBUF_EXPORT Reflection {
const FieldDescriptor* field,
MessageFactory* factory = NULL) const = 0;
+ // Appends an already-allocated object 'new_entry' to the repeated field
+ // specifyed by 'field' passing ownership to the message.
+ // TODO(tmarek): Make virtual after all subclasses have been
+ // updated.
+ virtual void AddAllocatedMessage(Message* message,
+ const FieldDescriptor* field,
+ Message* new_entry) const {}
+
// Get a RepeatedFieldRef object that can be used to read the underlying
// repeated field. The type parameter T must be set according to the
@@ -868,11 +887,20 @@ class LIBPROTOBUF_EXPORT Reflection {
// on field->cpp_type(),
// on field->field_option().ctype() (if ctype >= 0)
// of field->message_type() (if message_type != NULL).
- // We use 1 routine rather than 4 (const vs mutable) x (scalar vs pointer).
+ // We use 2 routine rather than 4 (const vs mutable) x (scalar vs pointer).
virtual void* MutableRawRepeatedField(
Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
int ctype, const Descriptor* message_type) const = 0;
+ // TODO(jieluo) - make it pure virtual after updating all the subclasses.
+ virtual const void* GetRawRepeatedField(
+ const Message& message, const FieldDescriptor* field,
+ FieldDescriptor::CppType cpptype, int ctype,
+ const Descriptor* message_type) const {
+ return MutableRawRepeatedField(
+ const_cast<Message*>(&message), field, cpptype, ctype, message_type);
+ }
+
// The following methods are used to implement (Mutable)RepeatedFieldRef.
// A Ref object will store a raw pointer to the repeated field data (obtained
// from RepeatedFieldData()) and a pointer to a Accessor (obtained from
@@ -887,6 +915,8 @@ class LIBPROTOBUF_EXPORT Reflection {
// "message_type" should be set to its descriptor. Otherwise "message_type"
// should be set to NULL. Implementations of this method should check whether
// "cpp_type"/"message_type" is consistent with the actual type of the field.
+ // We use 1 routine rather than 2 (const vs mutable) because it is protected
+ // and it doesn't change the message.
virtual void* RepeatedFieldData(
Message* message, const FieldDescriptor* field,
FieldDescriptor::CppType cpp_type,
@@ -902,14 +932,73 @@ class LIBPROTOBUF_EXPORT Reflection {
friend class RepeatedFieldRef;
template<typename T, typename Enable>
friend class MutableRepeatedFieldRef;
+ friend class ::google::protobuf::python::MapReflectionFriend;
// Special version for specialized implementations of string. We can't call
// MutableRawRepeatedField directly here because we don't have access to
// FieldOptions::* which are defined in descriptor.pb.h. Including that
// file here is not possible because it would cause a circular include cycle.
+ // We use 1 routine rather than 2 (const vs mutable) because it is private
+ // and mutable a repeated string field doesn't change the message.
void* MutableRawRepeatedString(
Message* message, const FieldDescriptor* field, bool is_string) const;
+ friend class MapReflectionTester;
+ // TODO(jieluo) - make the map APIs pure virtual after updating
+ // all the subclasses.
+ // Returns true if key is in map. Returns false if key is not in map field.
+ virtual bool ContainsMapKey(const Message& message,
+ const FieldDescriptor* field,
+ const MapKey& key) const {
+ return false;
+ }
+
+ // If key is in map field: Saves the value pointer to val and returns
+ // false. If key in not in map field: Insert the key into map, saves
+ // value pointer to val and retuns true.
+ virtual bool InsertOrLookupMapValue(Message* message,
+ const FieldDescriptor* field,
+ const MapKey& key,
+ MapValueRef* val) const {
+ return false;
+ }
+
+ // Delete and returns true if key is in the map field. Returns false
+ // otherwise.
+ virtual bool DeleteMapValue(Message* message,
+ const FieldDescriptor* field,
+ const MapKey& key) const {
+ return false;
+ }
+
+ // Returns a MaIterator referring to the first element in the map field.
+ // If the map field is empty, this function returns the same as
+ // reflection::MapEnd. Mutation to the field may invalidate the iterator.
+ virtual MapIterator MapBegin(
+ Message* message,
+ const FieldDescriptor* field) const;
+
+ // Returns a MapIterator referring to the theoretical element that would
+ // follow the last element in the map field. It does not point to any
+ // real element. Mutation to the field may invalidate the iterator.
+ virtual MapIterator MapEnd(
+ Message* message,
+ const FieldDescriptor* field) const;
+
+ // Get the number of <key, value> pair of a map field. The result may be
+ // different from FieldSize which can have duplicate keys.
+ virtual int MapSize(const Message& message,
+ const FieldDescriptor* field) const {
+ return 0;
+ }
+
+ // Help method for MapIterator.
+ friend class MapIterator;
+ virtual internal::MapFieldBase* MapData(
+ Message* message, const FieldDescriptor* field) const {
+ return NULL;
+ }
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reflection);
};
@@ -1025,10 +1114,9 @@ inline RepeatedPtrField<string>* Reflection::MutableRepeatedPtrField<string>(
template<>
inline const RepeatedPtrField<Message>& Reflection::GetRepeatedPtrField(
const Message& message, const FieldDescriptor* field) const {
- return *static_cast<RepeatedPtrField<Message>* >(
- MutableRawRepeatedField(const_cast<Message*>(&message), field,
- FieldDescriptor::CPPTYPE_MESSAGE, -1,
- NULL));
+ return *static_cast<const RepeatedPtrField<Message>* >(
+ GetRawRepeatedField(message, field, FieldDescriptor::CPPTYPE_MESSAGE,
+ -1, NULL));
}
template<>
@@ -1043,10 +1131,9 @@ inline RepeatedPtrField<Message>* Reflection::MutableRepeatedPtrField(
template<typename PB>
inline const RepeatedPtrField<PB>& Reflection::GetRepeatedPtrField(
const Message& message, const FieldDescriptor* field) const {
- return *static_cast<RepeatedPtrField<PB>* >(
- MutableRawRepeatedField(const_cast<Message*>(&message), field,
- FieldDescriptor::CPPTYPE_MESSAGE, -1,
- PB::default_instance().GetDescriptor()));
+ return *static_cast<const RepeatedPtrField<PB>* >(
+ GetRawRepeatedField(message, field, FieldDescriptor::CPPTYPE_MESSAGE,
+ -1, PB::default_instance().GetDescriptor()));
}
template<typename PB>
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index 4f63ad2b..5bd8bcfb 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -35,7 +35,9 @@
#include <google/protobuf/message_lite.h>
#include <google/protobuf/arena.h>
+#include <google/protobuf/repeated_field.h>
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
@@ -98,27 +100,19 @@ string InitializationErrorMessage(const char* action,
// call MergePartialFromCodedStream(). However, when parsing very small
// messages, every function call introduces significant overhead. To avoid
// this without reproducing code, we use these forced-inline helpers.
-//
-// Note: GCC only allows GOOGLE_ATTRIBUTE_ALWAYS_INLINE on declarations, not
-// definitions.
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineMergeFromCodedStream(
+ io::CodedInputStream* input, MessageLite* message);
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromCodedStream(
+ io::CodedInputStream* input, MessageLite* message);
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromCodedStream(
+ io::CodedInputStream* input, MessageLite* message);
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromArray(
+ const void* data, int size, MessageLite* message);
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromArray(
+ const void* data, int size, MessageLite* message);
+
inline bool InlineMergeFromCodedStream(io::CodedInputStream* input,
- MessageLite* message)
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
-inline bool InlineParseFromCodedStream(io::CodedInputStream* input,
- MessageLite* message)
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
-inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
- MessageLite* message)
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
-inline bool InlineParseFromArray(const void* data, int size,
- MessageLite* message)
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
-inline bool InlineParsePartialFromArray(const void* data, int size,
- MessageLite* message)
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
-
-bool InlineMergeFromCodedStream(io::CodedInputStream* input,
- MessageLite* message) {
+ MessageLite* message) {
if (!message->MergePartialFromCodedStream(input)) return false;
if (!message->IsInitialized()) {
GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *message);
@@ -127,26 +121,27 @@ bool InlineMergeFromCodedStream(io::CodedInputStream* input,
return true;
}
-bool InlineParseFromCodedStream(io::CodedInputStream* input,
- MessageLite* message) {
+inline bool InlineParseFromCodedStream(io::CodedInputStream* input,
+ MessageLite* message) {
message->Clear();
return InlineMergeFromCodedStream(input, message);
}
-bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
- MessageLite* message) {
+inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
+ MessageLite* message) {
message->Clear();
return message->MergePartialFromCodedStream(input);
}
-bool InlineParseFromArray(const void* data, int size, MessageLite* message) {
+inline bool InlineParseFromArray(
+ const void* data, int size, MessageLite* message) {
io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
return InlineParseFromCodedStream(&input, message) &&
input.ConsumedEntireMessage();
}
-bool InlineParsePartialFromArray(const void* data, int size,
- MessageLite* message) {
+inline bool InlineParsePartialFromArray(
+ const void* data, int size, MessageLite* message) {
io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
return InlineParsePartialFromCodedStream(&input, message) &&
input.ConsumedEntireMessage();
@@ -353,5 +348,18 @@ string MessageLite::SerializePartialAsString() const {
return output;
}
+namespace internal {
+template<>
+MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
+ const MessageLite* prototype, google::protobuf::Arena* arena) {
+ return prototype->New(arena);
+}
+template <>
+void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
+ MessageLite* to) {
+ to->CheckTypeAndMergeFrom(from);
+}
+} // namespace internal
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc
index 75d60b8b..2d4780fe 100644
--- a/src/google/protobuf/message_unittest.cc
+++ b/src/google/protobuf/message_unittest.cc
@@ -53,6 +53,7 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/metadata.h b/src/google/protobuf/metadata.h
index c5bab0a8..219645d3 100644
--- a/src/google/protobuf/metadata.h
+++ b/src/google/protobuf/metadata.h
@@ -56,7 +56,7 @@ namespace internal {
// The tagged pointer uses the LSB to disambiguate cases, and uses bit 0 == 0 to
// indicate an arena pointer and bit 0 == 1 to indicate a UFS+Arena-container
// pointer.
-class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
+class InternalMetadataWithArena {
public:
InternalMetadataWithArena() : ptr_(NULL) {}
explicit InternalMetadataWithArena(Arena* arena)
@@ -69,8 +69,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
ptr_ = NULL;
}
- inline const UnknownFieldSet& unknown_fields() const
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE const UnknownFieldSet& unknown_fields() const {
if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) {
return PtrValue<Container>()->unknown_fields_;
} else {
@@ -78,7 +77,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
}
}
- inline UnknownFieldSet* mutable_unknown_fields() GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE UnknownFieldSet* mutable_unknown_fields() {
if (GOOGLE_PREDICT_TRUE(have_unknown_fields())) {
return &PtrValue<Container>()->unknown_fields_;
} else {
@@ -86,7 +85,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
}
}
- inline Arena* arena() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE Arena* arena() const {
if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) {
return PtrValue<Container>()->arena_;
} else {
@@ -94,11 +93,11 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
}
}
- inline bool have_unknown_fields() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool have_unknown_fields() const {
return PtrTag() == kTagContainer;
}
- inline void Swap(InternalMetadataWithArena* other) GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(InternalMetadataWithArena* other) {
// Semantics here are that we swap only the unknown fields, not the arena
// pointer. We cannot simply swap ptr_ with other->ptr_ because we need to
// maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in
@@ -110,7 +109,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
}
}
- inline void* raw_arena_ptr() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* raw_arena_ptr() const {
return ptr_;
}
@@ -128,7 +127,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
static const intptr_t kPtrValueMask = ~kPtrTagMask;
// Accessors for pointer tag and pointer value.
- inline int PtrTag() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE int PtrTag() const {
return reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask;
}
diff --git a/src/google/protobuf/no_field_presence_test.cc b/src/google/protobuf/no_field_presence_test.cc
index 4b7b31d9..bc41beec 100644
--- a/src/google/protobuf/no_field_presence_test.cc
+++ b/src/google/protobuf/no_field_presence_test.cc
@@ -341,6 +341,46 @@ TEST(NoFieldPresenceTest, ReflectionHasFieldTest) {
EXPECT_EQ(false, r->HasField(message, field_string));
}
+TEST(NoFieldPresenceTest, ReflectionClearFieldTest) {
+ proto2_nofieldpresence_unittest::TestAllTypes message;
+
+ const google::protobuf::Reflection* r = message.GetReflection();
+ const google::protobuf::Descriptor* desc = message.GetDescriptor();
+
+ const google::protobuf::FieldDescriptor* field_int32 = desc->FindFieldByName(
+ "optional_int32");
+ const google::protobuf::FieldDescriptor* field_double = desc->FindFieldByName(
+ "optional_double");
+ const google::protobuf::FieldDescriptor* field_string = desc->FindFieldByName(
+ "optional_string");
+ const google::protobuf::FieldDescriptor* field_message = desc->FindFieldByName(
+ "optional_nested_message");
+ const google::protobuf::FieldDescriptor* field_lazy = desc->FindFieldByName(
+ "optional_lazy_message");
+
+ message.set_optional_int32(42);
+ r->ClearField(&message, field_int32);
+ EXPECT_EQ(0, message.optional_int32());
+
+ message.set_optional_double(42.0);
+ r->ClearField(&message, field_double);
+ EXPECT_EQ(0.0, message.optional_double());
+
+ message.set_optional_string("test");
+ r->ClearField(&message, field_string);
+ EXPECT_EQ("", message.optional_string());
+
+ message.mutable_optional_nested_message()->set_bb(1234);
+ r->ClearField(&message, field_message);
+ EXPECT_FALSE(message.has_optional_nested_message());
+ EXPECT_EQ(0, message.optional_nested_message().bb());
+
+ message.mutable_optional_lazy_message()->set_bb(42);
+ r->ClearField(&message, field_lazy);
+ EXPECT_FALSE(message.has_optional_lazy_message());
+ EXPECT_EQ(0, message.optional_lazy_message().bb());
+}
+
TEST(NoFieldPresenceTest, HasFieldOneofsTest) {
// check that HasField behaves properly for oneofs.
proto2_nofieldpresence_unittest::TestAllTypes message;
diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc
index da4be673..2838e0fc 100644
--- a/src/google/protobuf/proto3_arena_unittest.cc
+++ b/src/google/protobuf/proto3_arena_unittest.cc
@@ -119,7 +119,7 @@ void ExpectAllFieldsSet(const TestAllTypes& m) {
// proto3 and expect the arena support to be fully tested in proto2 unittests
// because proto3 shares most code with proto2.
-TEST(ArenaTest, Parsing) {
+TEST(Proto3ArenaTest, Parsing) {
TestAllTypes original;
SetAllFields(&original);
@@ -129,7 +129,7 @@ TEST(ArenaTest, Parsing) {
ExpectAllFieldsSet(*arena_message);
}
-TEST(ArenaTest, UnknownFields) {
+TEST(Proto3ArenaTest, UnknownFields) {
TestAllTypes original;
SetAllFields(&original);
@@ -150,7 +150,7 @@ TEST(ArenaTest, UnknownFields) {
arena_message->GetReflection()->GetUnknownFields(*arena_message).empty());
}
-TEST(ArenaTest, Swap) {
+TEST(Proto3ArenaTest, Swap) {
Arena arena1;
Arena arena2;
@@ -162,7 +162,7 @@ TEST(ArenaTest, Swap) {
EXPECT_EQ(&arena2, arena2_message->GetArena());
}
-TEST(ArenaTest, SetAllocatedMessage) {
+TEST(Proto3ArenaTest, SetAllocatedMessage) {
Arena arena;
TestAllTypes *arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
TestAllTypes::NestedMessage* nested = new TestAllTypes::NestedMessage;
@@ -171,7 +171,7 @@ TEST(ArenaTest, SetAllocatedMessage) {
EXPECT_EQ(118, arena_message->optional_nested_message().bb());
}
-TEST(ArenaTest, ReleaseMessage) {
+TEST(Proto3ArenaTest, ReleaseMessage) {
Arena arena;
TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
arena_message->mutable_optional_nested_message()->set_bb(118);
@@ -180,7 +180,7 @@ TEST(ArenaTest, ReleaseMessage) {
EXPECT_EQ(118, nested->bb());
}
-TEST(ArenaTest, MessageFieldClear) {
+TEST(Proto3ArenaTest, MessageFieldClear) {
// GitHub issue #310: https://github.com/google/protobuf/issues/310
Arena arena;
TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
@@ -190,6 +190,20 @@ TEST(ArenaTest, MessageFieldClear) {
arena_message->Clear();
}
+TEST(Proto3ArenaTest, MessageFieldClearViaReflection) {
+ Arena arena;
+ TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+ const Reflection* r = message->GetReflection();
+ const Descriptor* d = message->GetDescriptor();
+ const FieldDescriptor* msg_field = d->FindFieldByName(
+ "optional_nested_message");
+
+ message->mutable_optional_nested_message()->set_bb(1);
+ r->ClearField(message, msg_field);
+ EXPECT_FALSE(message->has_optional_nested_message());
+ EXPECT_EQ(0, message->optional_nested_message().bb());
+}
+
} // namespace
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/proto_cast.h b/src/google/protobuf/proto_cast.h
index e25c219f..dc0e9aca 100644
--- a/src/google/protobuf/proto_cast.h
+++ b/src/google/protobuf/proto_cast.h
@@ -33,6 +33,7 @@
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
// proto_cast<> is used to simulate over-the-wire conversion of one
diff --git a/src/google/protobuf/proto_cast_test.cc b/src/google/protobuf/proto_cast_test.cc
index eb101eb6..a8f43ae4 100644
--- a/src/google/protobuf/proto_cast_test.cc
+++ b/src/google/protobuf/proto_cast_test.cc
@@ -32,7 +32,7 @@
#include <google/protobuf/util/unknown_enum_test.pb.h>
#include <gtest/gtest.h>
-#include <google/protobuf/testing/gmock.h>
+#include <gmock/gmock.h>
namespace google {
using google::protobuf::util::UpRevision;
diff --git a/src/google/protobuf/reflection.h b/src/google/protobuf/reflection.h
index 4ff0f6b4..671aafdc 100755
--- a/src/google/protobuf/reflection.h
+++ b/src/google/protobuf/reflection.h
@@ -553,7 +553,7 @@ struct RefTypeTraits<
template<typename T>
struct RefTypeTraits<
- T, typename internal::enable_if<internal::is_same<string, T>::value>::type> {
+ T, typename internal::enable_if< ::google::protobuf::internal::is_same<string, T>::value>::type> {
typedef RepeatedFieldRefIterator<T> iterator;
typedef RepeatedFieldAccessor AccessorType;
typedef string AccessorValueType;
diff --git a/src/google/protobuf/reflection_ops_unittest.cc b/src/google/protobuf/reflection_ops_unittest.cc
index 32740ea4..88d6bfb6 100644
--- a/src/google/protobuf/reflection_ops_unittest.cc
+++ b/src/google/protobuf/reflection_ops_unittest.cc
@@ -37,6 +37,7 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/test_util.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc
index e5aedadc..949e0a23 100644
--- a/src/google/protobuf/repeated_field.cc
+++ b/src/google/protobuf/repeated_field.cc
@@ -35,6 +35,7 @@
#include <algorithm>
#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
namespace google {
@@ -53,13 +54,17 @@ void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) {
Arena* arena = GetArenaNoVirtual();
new_size = max(kMinRepeatedFieldAllocationSize,
max(total_size_ * 2, new_size));
+ GOOGLE_CHECK_LE(new_size,
+ (std::numeric_limits<size_t>::max() - kRepHeaderSize) /
+ sizeof(old_rep->elements[0]))
+ << "Requested size is too large to fit into size_t.";
if (arena == NULL) {
rep_ = reinterpret_cast<Rep*>(
- new char[kRepHeaderSize + sizeof(old_rep->elements[0])*new_size]);
+ new char[kRepHeaderSize + sizeof(old_rep->elements[0]) * new_size]);
} else {
rep_ = reinterpret_cast<Rep*>(
::google::protobuf::Arena::CreateArray<char>(arena,
- kRepHeaderSize + sizeof(old_rep->elements[0])*new_size));
+ kRepHeaderSize + sizeof(old_rep->elements[0]) * new_size));
}
total_size_ = new_size;
if (old_rep && old_rep->allocated_size > 0) {
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 9c84ed98..b10e7a95 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -54,6 +54,7 @@
#include <string>
#include <iterator>
#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/type_traits.h>
#include <google/protobuf/arena.h>
@@ -361,7 +362,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
// To parse directly into a proto2 generated class, the upb class GMR_Handlers
// needs to be able to modify a RepeatedPtrFieldBase directly.
- friend class LIBPROTOBUF_EXPORT upb::google_opensource::GMR_Handlers;
+ friend class upb::google_opensource::GMR_Handlers;
RepeatedPtrFieldBase();
explicit RepeatedPtrFieldBase(::google::protobuf::Arena* arena);
@@ -408,7 +409,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
const typename TypeHandler::Type* const* data() const;
template <typename TypeHandler>
- inline void Swap(RepeatedPtrFieldBase* other) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(RepeatedPtrFieldBase* other);
void SwapElements(int index1, int index2);
@@ -461,8 +462,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler> GOOGLE_ATTRIBUTE_NOINLINE
void AddAllocatedSlowWithCopy(typename TypeHandler::Type* value,
Arena* value_arena,
- Arena* my_arena)
-;
+ Arena* my_arena);
template <typename TypeHandler> GOOGLE_ATTRIBUTE_NOINLINE
void AddAllocatedSlowWithoutCopy(typename TypeHandler::Type* value);
@@ -472,7 +472,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
typename TypeHandler::Type* ReleaseLastInternal(google::protobuf::internal::false_type);
template<typename TypeHandler> GOOGLE_ATTRIBUTE_NOINLINE
- inline void SwapFallback(RepeatedPtrFieldBase* other);
+ void SwapFallback(RepeatedPtrFieldBase* other);
inline Arena* GetArenaNoVirtual() const {
return arena_;
@@ -541,20 +541,10 @@ class GenericTypeHandler {
}
// We force NewFromPrototype() and Delete() to be non-inline to reduce code
// size: else, several other methods get inlined copies of message types'
- // constructors and destructors. Note that the GOOGLE_ATTRIBUTE_NOINLINE macro
- // requires the 'inline' storage class here, which is somewhat confusing, but
- // the compiler does the right thing.
- GOOGLE_ATTRIBUTE_NOINLINE
- static inline GenericType* NewFromPrototype(const GenericType* prototype,
- ::google::protobuf::Arena* arena = NULL) {
- return New(arena);
- }
- GOOGLE_ATTRIBUTE_NOINLINE
- static inline void Delete(GenericType* value, Arena* arena) {
- if (arena == NULL) {
- delete value;
- }
- }
+ // constructors and destructors.
+ GOOGLE_ATTRIBUTE_NOINLINE static GenericType* NewFromPrototype(
+ const GenericType* prototype, ::google::protobuf::Arena* arena = NULL);
+ GOOGLE_ATTRIBUTE_NOINLINE static void Delete(GenericType* value, Arena* arena);
static inline ::google::protobuf::Arena* GetArena(GenericType* value) {
return ::google::protobuf::Arena::GetArena<Type>(value);
}
@@ -563,11 +553,8 @@ class GenericTypeHandler {
}
static inline void Clear(GenericType* value) { value->Clear(); }
-
- GOOGLE_ATTRIBUTE_NOINLINE
- static inline void Merge(const GenericType& from, GenericType* to) {
- to->MergeFrom(from);
- }
+ GOOGLE_ATTRIBUTE_NOINLINE static void Merge(const GenericType& from,
+ GenericType* to);
static inline int SpaceUsed(const GenericType& value) {
return value.SpaceUsed();
}
@@ -576,11 +563,31 @@ class GenericTypeHandler {
}
};
-template<>
-inline MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
- const MessageLite* prototype, google::protobuf::Arena* arena) {
- return prototype->New(arena);
+template <typename GenericType>
+GenericType* GenericTypeHandler<GenericType>::NewFromPrototype(
+ const GenericType* prototype, ::google::protobuf::Arena* arena) {
+ return New(arena);
}
+template <typename GenericType>
+void GenericTypeHandler<GenericType>::Delete(GenericType* value, Arena* arena) {
+ if (arena == NULL) {
+ delete value;
+ }
+}
+template <typename GenericType>
+void GenericTypeHandler<GenericType>::Merge(const GenericType& from,
+ GenericType* to) {
+ to->MergeFrom(from);
+}
+
+// NewFromPrototype() and Merge() cannot be defined here; if they're declared
+// inline the compiler will complain about not matching GOOGLE_ATTRIBUTE_NOINLINE
+// above, and if not, compilation will result in multiple definitions. These
+// are therefore declared as specializations here and defined in
+// message_lite.cc.
+template<>
+MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
+ const MessageLite* prototype, google::protobuf::Arena* arena);
template<>
inline google::protobuf::Arena* GenericTypeHandler<MessageLite>::GetArena(
MessageLite* value) {
@@ -591,14 +598,9 @@ inline void* GenericTypeHandler<MessageLite>::GetMaybeArenaPointer(
MessageLite* value) {
return value->GetMaybeArenaPointer();
}
-
-// Implements GenericTypeHandler specialization required by RepeatedPtrFields
-// to work with MessageLite type.
template <>
-inline void GenericTypeHandler<MessageLite>::Merge(
- const MessageLite& from, MessageLite* to) {
- to->CheckTypeAndMergeFrom(from);
-}
+void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
+ MessageLite* to);
// Declarations of the specialization as we cannot define them here, as the
// header that defines ProtocolMessage depends on types defined in this header.
@@ -647,7 +649,8 @@ inline const Message& GenericTypeHandler<Message>::default_instance() {
// StringTypeHandler is exported. So, we factor out StringTypeHandlerBase,
// export that, then make StringTypeHandler be a subclass which is NOT
// exported.
-// TODO(kenton): There has to be a better way.
+// TODO(kenton): Now that StringSpaceUsedExcludingSelf() is in the lite
+// library, this can be cleaned up.
class LIBPROTOBUF_EXPORT StringTypeHandlerBase {
public:
typedef string Type;
@@ -1221,13 +1224,17 @@ void RepeatedField<Element>::Reserve(int new_size) {
Arena* arena = GetArenaNoVirtual();
new_size = max(google::protobuf::internal::kMinRepeatedFieldAllocationSize,
max(total_size_ * 2, new_size));
+ GOOGLE_CHECK_LE(static_cast<size_t>(new_size),
+ (std::numeric_limits<size_t>::max() - kRepHeaderSize) /
+ sizeof(Element))
+ << "Requested size is too large to fit into size_t.";
if (arena == NULL) {
rep_ = reinterpret_cast<Rep*>(
- new char[kRepHeaderSize + sizeof(Element)*new_size]);
+ new char[kRepHeaderSize + sizeof(Element) * new_size]);
} else {
rep_ = reinterpret_cast<Rep*>(
::google::protobuf::Arena::CreateArray<char>(arena,
- kRepHeaderSize + sizeof(Element)*new_size));
+ kRepHeaderSize + sizeof(Element) * new_size));
}
rep_->arena = arena;
int old_total_size = total_size_;
@@ -1342,7 +1349,7 @@ inline void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) {
}
template <typename TypeHandler>
-inline void RepeatedPtrFieldBase::SwapFallback(RepeatedPtrFieldBase* other) {
+void RepeatedPtrFieldBase::SwapFallback(RepeatedPtrFieldBase* other) {
GOOGLE_DCHECK(other->GetArenaNoVirtual() != GetArenaNoVirtual());
// Copy semantics in this case. We try to improve efficiency by placing the
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index af397932..b45664b0 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -42,6 +42,7 @@
#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/stubs/strutil.h>
@@ -1429,7 +1430,6 @@ class RepeatedFieldInsertionIteratorsTest : public testing::Test {
std::copy(nested_ptrs.begin(), nested_ptrs.end(),
RepeatedFieldBackInserter(
protobuffer.mutable_repeated_nested_message()));
-
}
virtual void TearDown() {
diff --git a/src/google/protobuf/service.h b/src/google/protobuf/service.h
index cc0b45d4..ad6f9685 100644
--- a/src/google/protobuf/service.h
+++ b/src/google/protobuf/service.h
@@ -74,12 +74,12 @@
//
// To call a remote MyServiceImpl, first you need an RpcChannel connected to it.
// How to construct a channel depends, again, on your RPC implementation.
-// Here we use a hypothentical "MyRpcChannel" as an example:
+// Here we use a hypothetical "MyRpcChannel" as an example:
// MyRpcChannel channel("rpc:hostname:1234/myservice");
// MyRpcController controller;
// MyServiceImpl::Stub stub(&channel);
// FooRequest request;
-// FooRespnose response;
+// FooResponse response;
//
// // ... fill in request ...
//
@@ -102,6 +102,7 @@
#include <string>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/callback.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc
index 5c88363f..c8397639 100644
--- a/src/google/protobuf/source_context.pb.cc
+++ b/src/google/protobuf/source_context.pb.cc
@@ -81,9 +81,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto() {
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n$google/protobuf/source_context.proto\022\017"
"google.protobuf\"\"\n\rSourceContext\022\021\n\tfile"
- "_name\030\001 \001(\tBR\n\023com.google.protobufB\022Sour"
- "ceContextProtoP\001\242\002\003GPB\252\002\036Google.Protobuf"
- ".WellKnownTypesb\006proto3", 183);
+ "_name\030\001 \001(\tBU\n\023com.google.protobufB\022Sour"
+ "ceContextProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Proto"
+ "buf.WellKnownTypesb\006proto3", 186);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/source_context.proto", &protobuf_RegisterTypes);
SourceContext::default_instance_ = new SourceContext();
@@ -194,10 +194,10 @@ bool SourceContext::MergePartialFromCodedStream(
if (tag == 10) {
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_file_name()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->file_name().data(), this->file_name().length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.SourceContext.file_name");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.SourceContext.file_name"));
} else {
goto handle_unusual;
}
@@ -231,9 +231,9 @@ void SourceContext::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_start:google.protobuf.SourceContext)
// optional string file_name = 1;
if (this->file_name().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->file_name().data(), this->file_name().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.SourceContext.file_name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->file_name(), output);
@@ -247,9 +247,9 @@ void SourceContext::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceContext)
// optional string file_name = 1;
if (this->file_name().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->file_name().data(), this->file_name().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.SourceContext.file_name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
diff --git a/src/google/protobuf/source_context.proto b/src/google/protobuf/source_context.proto
index 98d4920a..e9a27d65 100644
--- a/src/google/protobuf/source_context.proto
+++ b/src/google/protobuf/source_context.proto
@@ -34,10 +34,10 @@ package google.protobuf;
option java_multiple_files = true;
option java_outer_classname = "SourceContextProto";
option java_package = "com.google.protobuf";
+option java_generate_equals_and_hash = true;
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
option objc_class_prefix = "GPB";
-
// `SourceContext` represents information about the source of a
// protobuf element, like the file in which it is defined.
message SourceContext {
diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc
index a7e2eafd..d5f89122 100644
--- a/src/google/protobuf/struct.pb.cc
+++ b/src/google/protobuf/struct.pb.cc
@@ -301,6 +301,10 @@ bool Struct::MergePartialFromCodedStream(
DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
input, entry.get()));
(*mutable_fields())[entry->key()].Swap(entry->mutable_value());
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+ entry->key().data(), entry->key().length(),
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Struct.FieldsEntry.key"));
} else {
goto handle_unusual;
}
@@ -343,6 +347,10 @@ void Struct::SerializeWithCachedSizes(
entry.reset(fields_.NewEntryWrapper(it->first, it->second));
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
1, *entry, output);
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+ it->first.data(), it->first.length(),
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+ "google.protobuf.Struct.FieldsEntry.key");
}
}
@@ -362,6 +370,10 @@ void Struct::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
1, *entry, target);
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+ it->first.data(), it->first.length(),
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+ "google.protobuf.Struct.FieldsEntry.key");
}
}
@@ -631,10 +643,10 @@ bool Value::MergePartialFromCodedStream(
parse_string_value:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_string_value()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->string_value().data(), this->string_value().length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.Value.string_value");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Value.string_value"));
} else {
goto handle_unusual;
}
@@ -721,9 +733,9 @@ void Value::SerializeWithCachedSizes(
// optional string string_value = 3;
if (has_string_value()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->string_value().data(), this->string_value().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Value.string_value");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
3, this->string_value(), output);
@@ -765,9 +777,9 @@ void Value::SerializeWithCachedSizes(
// optional string string_value = 3;
if (has_string_value()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->string_value().data(), this->string_value().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Value.string_value");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
@@ -1114,10 +1126,11 @@ void Value::clear_struct_value() {
}
const ::google::protobuf::Struct& Value::struct_value() const {
// @@protoc_insertion_point(field_get:google.protobuf.Value.struct_value)
- return has_struct_value() ? *kind_.struct_value_
- : ::google::protobuf::Struct::default_instance();
+ return has_struct_value()
+ ? *kind_.struct_value_
+ : ::google::protobuf::Struct::default_instance();
}
- ::google::protobuf::Struct* Value::mutable_struct_value() {
+::google::protobuf::Struct* Value::mutable_struct_value() {
if (!has_struct_value()) {
clear_kind();
set_has_struct_value();
@@ -1126,7 +1139,7 @@ void Value::clear_struct_value() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Value.struct_value)
return kind_.struct_value_;
}
- ::google::protobuf::Struct* Value::release_struct_value() {
+::google::protobuf::Struct* Value::release_struct_value() {
if (has_struct_value()) {
clear_has_kind();
::google::protobuf::Struct* temp = kind_.struct_value_;
@@ -1136,7 +1149,7 @@ void Value::clear_struct_value() {
return NULL;
}
}
- void Value::set_allocated_struct_value(::google::protobuf::Struct* struct_value) {
+void Value::set_allocated_struct_value(::google::protobuf::Struct* struct_value) {
clear_kind();
if (struct_value) {
set_has_struct_value();
@@ -1160,10 +1173,11 @@ void Value::clear_list_value() {
}
const ::google::protobuf::ListValue& Value::list_value() const {
// @@protoc_insertion_point(field_get:google.protobuf.Value.list_value)
- return has_list_value() ? *kind_.list_value_
- : ::google::protobuf::ListValue::default_instance();
+ return has_list_value()
+ ? *kind_.list_value_
+ : ::google::protobuf::ListValue::default_instance();
}
- ::google::protobuf::ListValue* Value::mutable_list_value() {
+::google::protobuf::ListValue* Value::mutable_list_value() {
if (!has_list_value()) {
clear_kind();
set_has_list_value();
@@ -1172,7 +1186,7 @@ void Value::clear_list_value() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Value.list_value)
return kind_.list_value_;
}
- ::google::protobuf::ListValue* Value::release_list_value() {
+::google::protobuf::ListValue* Value::release_list_value() {
if (has_list_value()) {
clear_has_kind();
::google::protobuf::ListValue* temp = kind_.list_value_;
@@ -1182,7 +1196,7 @@ void Value::clear_list_value() {
return NULL;
}
}
- void Value::set_allocated_list_value(::google::protobuf::ListValue* list_value) {
+void Value::set_allocated_list_value(::google::protobuf::ListValue* list_value) {
clear_kind();
if (list_value) {
set_has_list_value();
@@ -1422,28 +1436,28 @@ int ListValue::values_size() const {
void ListValue::clear_values() {
values_.Clear();
}
- const ::google::protobuf::Value& ListValue::values(int index) const {
+const ::google::protobuf::Value& ListValue::values(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.ListValue.values)
return values_.Get(index);
}
- ::google::protobuf::Value* ListValue::mutable_values(int index) {
+::google::protobuf::Value* ListValue::mutable_values(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.ListValue.values)
return values_.Mutable(index);
}
- ::google::protobuf::Value* ListValue::add_values() {
+::google::protobuf::Value* ListValue::add_values() {
// @@protoc_insertion_point(field_add:google.protobuf.ListValue.values)
return values_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >&
-ListValue::values() const {
- // @@protoc_insertion_point(field_list:google.protobuf.ListValue.values)
- return values_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >*
ListValue::mutable_values() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.ListValue.values)
return &values_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >&
+ListValue::values() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.ListValue.values)
+ return values_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h
index 2889c8fe..0527c812 100644
--- a/src/google/protobuf/struct.pb.h
+++ b/src/google/protobuf/struct.pb.h
@@ -40,9 +40,9 @@ void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
void protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto();
void protobuf_ShutdownFile_google_2fprotobuf_2fstruct_2eproto();
+class ListValue;
class Struct;
class Value;
-class ListValue;
enum NullValue {
NULL_VALUE = 0,
@@ -383,10 +383,10 @@ class LIBPROTOBUF_EXPORT ListValue : public ::google::protobuf::Message {
const ::google::protobuf::Value& values(int index) const;
::google::protobuf::Value* mutable_values(int index);
::google::protobuf::Value* add_values();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >&
- values() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >*
mutable_values();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >&
+ values() const;
// @@protoc_insertion_point(class_scope:google.protobuf.ListValue)
private:
@@ -612,10 +612,11 @@ inline void Value::clear_struct_value() {
clear_has_kind();
}
}
-inline const ::google::protobuf::Struct& Value::struct_value() const {
+inline const ::google::protobuf::Struct& Value::struct_value() const {
// @@protoc_insertion_point(field_get:google.protobuf.Value.struct_value)
- return has_struct_value() ? *kind_.struct_value_
- : ::google::protobuf::Struct::default_instance();
+ return has_struct_value()
+ ? *kind_.struct_value_
+ : ::google::protobuf::Struct::default_instance();
}
inline ::google::protobuf::Struct* Value::mutable_struct_value() {
if (!has_struct_value()) {
@@ -658,10 +659,11 @@ inline void Value::clear_list_value() {
clear_has_kind();
}
}
-inline const ::google::protobuf::ListValue& Value::list_value() const {
+inline const ::google::protobuf::ListValue& Value::list_value() const {
// @@protoc_insertion_point(field_get:google.protobuf.Value.list_value)
- return has_list_value() ? *kind_.list_value_
- : ::google::protobuf::ListValue::default_instance();
+ return has_list_value()
+ ? *kind_.list_value_
+ : ::google::protobuf::ListValue::default_instance();
}
inline ::google::protobuf::ListValue* Value::mutable_list_value() {
if (!has_list_value()) {
@@ -723,16 +725,16 @@ inline ::google::protobuf::Value* ListValue::add_values() {
// @@protoc_insertion_point(field_add:google.protobuf.ListValue.values)
return values_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >&
-ListValue::values() const {
- // @@protoc_insertion_point(field_list:google.protobuf.ListValue.values)
- return values_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >*
ListValue::mutable_values() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.ListValue.values)
return &values_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >&
+ListValue::values() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.ListValue.values)
+ return values_;
+}
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
// -------------------------------------------------------------------
diff --git a/src/google/protobuf/struct.proto b/src/google/protobuf/struct.proto
index 4ff10cd0..b3e9e699 100644
--- a/src/google/protobuf/struct.proto
+++ b/src/google/protobuf/struct.proto
@@ -45,6 +45,8 @@ option objc_class_prefix = "GPB";
// scripting languages like JS a struct is represented as an
// object. The details of that representation are described together
// with the proto support for the language.
+//
+// The JSON representation for `Struct` is JSON object.
message Struct {
// Map of dynamically typed values.
map<string, Value> fields = 1;
@@ -54,37 +56,39 @@ message Struct {
// null, a number, a string, a boolean, a recursive struct value, or a
// list of values. A producer of value is expected to set one of that
// variants, absence of any variant indicates an error.
+//
+// The JSON representation for `Value` is JSON value.
message Value {
+ // The kind of value.
oneof kind {
// Represents a null value.
NullValue null_value = 1;
-
// Represents a double value.
double number_value = 2;
-
// Represents a string value.
string string_value = 3;
-
// Represents a boolean value.
bool bool_value = 4;
-
// Represents a structured value.
Struct struct_value = 5;
-
// Represents a repeated `Value`.
ListValue list_value = 6;
}
}
+// `NullValue` is a singleton enumeration to represent the null value for the
+// `Value` type union.
+//
+// The JSON representation for `NullValue` is JSON `null`.
+enum NullValue {
+ // Null value.
+ NULL_VALUE = 0;
+}
+
// `ListValue` is a wrapper around a repeated field of values.
+//
+// The JSON representation for `ListValue` is JSON array.
message ListValue {
// Repeated field of dynamically typed values.
repeated Value values = 1;
}
-
-// `NullValue` is a singleton enumeration to represent the null
-// value for the `Value` type union.
-enum NullValue {
- // Null value.
- NULL_VALUE = 0;
-}
diff --git a/src/google/protobuf/stubs/atomicops.h b/src/google/protobuf/stubs/atomicops.h
index cd20caac..5fa31b0a 100644
--- a/src/google/protobuf/stubs/atomicops.h
+++ b/src/google/protobuf/stubs/atomicops.h
@@ -173,7 +173,7 @@ Atomic64 Release_Load(volatile const Atomic64* ptr);
// Include our platform specific implementation.
#define GOOGLE_PROTOBUF_ATOMICOPS_ERROR \
-#error "Atomic operations are not supported on your platform"
+"Atomic operations are not supported on your platform"
// ThreadSanitizer, http://clang.llvm.org/docs/ThreadSanitizer.html.
#if defined(THREAD_SANITIZER)
@@ -183,7 +183,7 @@ Atomic64 Release_Load(volatile const Atomic64* ptr);
#if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64)
#include <google/protobuf/stubs/atomicops_internals_x86_msvc.h>
#else
-GOOGLE_PROTOBUF_ATOMICOPS_ERROR
+#error GOOGLE_PROTOBUF_ATOMICOPS_ERROR
#endif
// Solaris
@@ -218,15 +218,15 @@ GOOGLE_PROTOBUF_ATOMICOPS_ERROR
#if __has_extension(c_atomic)
#include <google/protobuf/stubs/atomicops_internals_generic_gcc.h>
#else
-GOOGLE_PROTOBUF_ATOMICOPS_ERROR
+#error GOOGLE_PROTOBUF_ATOMICOPS_ERROR
#endif
#else
-GOOGLE_PROTOBUF_ATOMICOPS_ERROR
+#error GOOGLE_PROTOBUF_ATOMICOPS_ERROR
#endif
// Unknown.
#else
-GOOGLE_PROTOBUF_ATOMICOPS_ERROR
+#error GOOGLE_PROTOBUF_ATOMICOPS_ERROR
#endif
// On some platforms we need additional declarations to make AtomicWord
diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc
index d470fc72..54dbafab 100644
--- a/src/google/protobuf/stubs/common.cc
+++ b/src/google/protobuf/stubs/common.cc
@@ -35,8 +35,10 @@
#include <google/protobuf/stubs/status.h>
#include <google/protobuf/stubs/stringpiece.h>
#include <google/protobuf/stubs/strutil.h>
-#include <stdio.h>
+#include <google/protobuf/stubs/int128.h>
#include <errno.h>
+#include <sstream>
+#include <stdio.h>
#include <vector>
#ifdef _WIN32
@@ -48,6 +50,9 @@
#else
#error "No suitable threading library available."
#endif
+#if defined(__ANDROID__)
+#include <android/log.h>
+#endif
namespace google {
namespace protobuf {
@@ -104,7 +109,43 @@ string VersionString(int version) {
// emulates google3/base/logging.cc
namespace internal {
+#if defined(__ANDROID__)
+inline void DefaultLogHandler(LogLevel level, const char* filename, int line,
+ const string& message) {
+#ifdef GOOGLE_PROTOBUF_MIN_LOG_LEVEL
+ if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) {
+ return;
+ }
+ static const char* level_names[] = {"INFO", "WARNING", "ERROR", "FATAL"};
+
+ static const int android_log_levels[] = {
+ ANDROID_LOG_INFO, // LOG(INFO),
+ ANDROID_LOG_WARN, // LOG(WARNING)
+ ANDROID_LOG_ERROR, // LOG(ERROR)
+ ANDROID_LOG_FATAL, // LOG(FATAL)
+ };
+ // Bound the logging level.
+ const int android_log_level = android_log_levels[level];
+ ::std::ostringstream ostr;
+ ostr << "[libprotobuf " << level_names[level] << " " << filename << ":"
+ << line << "] " << message.c_str();
+
+ // Output the log string the Android log at the appropriate level.
+ __android_log_write(android_log_level, "libprotobuf-native",
+ ostr.str().c_str());
+ // Also output to std::cerr.
+ fprintf(stderr, "%s", ostr.str().c_str());
+ fflush(stderr);
+
+ // Indicate termination if needed.
+ if (android_log_level == ANDROID_LOG_FATAL) {
+ __android_log_write(ANDROID_LOG_FATAL, "libprotobuf-native",
+ "terminating.\n");
+ }
+#endif
+}
+#else
void DefaultLogHandler(LogLevel level, const char* filename, int line,
const string& message) {
static const char* level_names[] = { "INFO", "WARNING", "ERROR", "FATAL" };
@@ -115,6 +156,7 @@ void DefaultLogHandler(LogLevel level, const char* filename, int line,
level_names[level], filename, line, message.c_str());
fflush(stderr); // Needed on MSVC.
}
+#endif
void NullLogHandler(LogLevel /* level */, const char* /* filename */,
int /* line */, const string& /* message */) {
@@ -154,22 +196,19 @@ LogMessage& LogMessage::operator<<(const StringPiece& value) {
return *this;
}
-LogMessage& LogMessage::operator<<(long long value) {
- message_ += SimpleItoa(value);
- return *this;
-}
-
-LogMessage& LogMessage::operator<<(unsigned long long value) {
- message_ += SimpleItoa(value);
- return *this;
-}
-
LogMessage& LogMessage::operator<<(
const ::google::protobuf::util::Status& status) {
message_ += status.ToString();
return *this;
}
+LogMessage& LogMessage::operator<<(const uint128& value) {
+ std::ostringstream str;
+ str << value;
+ message_ += str.str();
+ return *this;
+}
+
// Since this is just for logging, we don't care if the current locale changes
// the results -- in fact, we probably prefer that. So we use snprintf()
// instead of Simple*toa().
@@ -194,6 +233,8 @@ DECLARE_STREAM_OPERATOR(long , "%ld")
DECLARE_STREAM_OPERATOR(unsigned long, "%lu")
DECLARE_STREAM_OPERATOR(double , "%g" )
DECLARE_STREAM_OPERATOR(void* , "%p" )
+DECLARE_STREAM_OPERATOR(long long , "%" GOOGLE_LL_FORMAT "d")
+DECLARE_STREAM_OPERATOR(unsigned long long, "%" GOOGLE_LL_FORMAT "u")
#undef DECLARE_STREAM_OPERATOR
LogMessage::LogMessage(LogLevel level, const char* filename, int line)
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index de866e14..88e7084f 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -35,6 +35,7 @@
#ifndef GOOGLE_PROTOBUF_COMMON_H__
#define GOOGLE_PROTOBUF_COMMON_H__
+#include <string>
#include <google/protobuf/stubs/port.h>
#include <google/protobuf/stubs/macros.h>
@@ -137,12 +138,35 @@ std::string LIBPROTOBUF_EXPORT VersionString(int version);
// ===================================================================
// from google3/util/utf8/public/unilib.h
+class StringPiece;
namespace internal {
// Checks if the buffer contains structurally-valid UTF-8. Implemented in
// structurally_valid.cc.
LIBPROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len);
+inline bool IsStructurallyValidUTF8(const std::string& str) {
+ return IsStructurallyValidUTF8(str.data(), str.length());
+}
+
+// Returns initial number of bytes of structually valid UTF-8.
+LIBPROTOBUF_EXPORT int UTF8SpnStructurallyValid(const StringPiece& str);
+
+// Coerce UTF-8 byte string in src_str to be
+// a structurally-valid equal-length string by selectively
+// overwriting illegal bytes with replace_char (typically ' ' or '?').
+// replace_char must be legal printable 7-bit Ascii 0x20..0x7e.
+// src_str is read-only.
+//
+// Returns pointer to output buffer, src_str.data() if no changes were made,
+// or idst if some bytes were changed. idst is allocated by the caller
+// and must be at least as big as src_str
+//
+// Optimized for: all structurally valid and no byte copying is done.
+//
+LIBPROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid(
+ const StringPiece& str, char* dst, char replace_char);
+
} // namespace internal
diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h
index 9a6b217a..e7b3771f 100755
--- a/src/google/protobuf/stubs/hash.h
+++ b/src/google/protobuf/stubs/hash.h
@@ -41,10 +41,10 @@
#define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1
#define GOOGLE_PROTOBUF_HAVE_HASH_SET 1
-// Use C++11 unordered_{map|set} if available. Otherwise, libc++ always support
-// unordered_{map|set}
-#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X) || \
- defined(_LIBCPP_VERSION)
+// Use C++11 unordered_{map|set} if available.
+#if ((_LIBCPP_STD_VER >= 11) || \
+ (((__cplusplus >= 201103L) || defined(__GXX_EXPERIMENTAL_CXX0X)) && \
+ (__GLIBCXX__ > 20090421)))
# define GOOGLE_PROTOBUF_HAS_CXX11_HASH
// For XCode >= 4.6: the compiler is clang with libc++.
@@ -103,8 +103,8 @@
# define GOOGLE_PROTOBUF_HAS_CXX11_HASH
# define GOOGLE_PROTOBUF_HASH_COMPARE std::hash_compare
# elif _MSC_VER >= 1500 // Since Visual Studio 2008
-# define GOOGLE_PROTOBUF_HAS_TR1
-# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
+# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP
+# undef GOOGLE_PROTOBUF_HAVE_HASH_SET
# elif _MSC_VER >= 1310
# define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext
# include <hash_map>
@@ -143,6 +143,11 @@
# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set
#endif
+# define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START \
+ namespace google { \
+ namespace protobuf {
+# define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END }}
+
#undef GOOGLE_PROTOBUF_HAS_CXX11_HASH
#undef GOOGLE_PROTOBUF_HAS_TR1
diff --git a/src/google/protobuf/stubs/int128.cc b/src/google/protobuf/stubs/int128.cc
new file mode 100644
index 00000000..9f4fb824
--- /dev/null
+++ b/src/google/protobuf/stubs/int128.cc
@@ -0,0 +1,200 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/stubs/int128.h>
+
+#include <iomanip>
+#include <iostream> // NOLINT(readability/streams)
+#include <sstream>
+
+namespace google {
+namespace protobuf {
+
+const uint128_pod kuint128max = {
+ static_cast<uint64>(GOOGLE_LONGLONG(0xFFFFFFFFFFFFFFFF)),
+ static_cast<uint64>(GOOGLE_LONGLONG(0xFFFFFFFFFFFFFFFF))
+};
+
+// Returns the 0-based position of the last set bit (i.e., most significant bit)
+// in the given uint64. The argument may not be 0.
+//
+// For example:
+// Given: 5 (decimal) == 101 (binary)
+// Returns: 2
+#define STEP(T, n, pos, sh) \
+ do { \
+ if ((n) >= (static_cast<T>(1) << (sh))) { \
+ (n) = (n) >> (sh); \
+ (pos) |= (sh); \
+ } \
+ } while (0)
+static inline int Fls64(uint64 n) {
+ GOOGLE_DCHECK_NE(0, n);
+ int pos = 0;
+ STEP(uint64, n, pos, 0x20);
+ uint32 n32 = n;
+ STEP(uint32, n32, pos, 0x10);
+ STEP(uint32, n32, pos, 0x08);
+ STEP(uint32, n32, pos, 0x04);
+ return pos + ((GOOGLE_ULONGLONG(0x3333333322221100) >> (n32 << 2)) & 0x3);
+}
+#undef STEP
+
+// Like Fls64() above, but returns the 0-based position of the last set bit
+// (i.e., most significant bit) in the given uint128. The argument may not be 0.
+static inline int Fls128(uint128 n) {
+ if (uint64 hi = Uint128High64(n)) {
+ return Fls64(hi) + 64;
+ }
+ return Fls64(Uint128Low64(n));
+}
+
+// Long division/modulo for uint128 implemented using the shift-subtract
+// division algorithm adapted from:
+// http://stackoverflow.com/questions/5386377/division-without-using
+void uint128::DivModImpl(uint128 dividend, uint128 divisor,
+ uint128* quotient_ret, uint128* remainder_ret) {
+ if (divisor == 0) {
+ GOOGLE_LOG(FATAL) << "Division or mod by zero: dividend.hi=" << dividend.hi_
+ << ", lo=" << dividend.lo_;
+ }
+
+ if (divisor > dividend) {
+ *quotient_ret = 0;
+ *remainder_ret = dividend;
+ return;
+ }
+
+ if (divisor == dividend) {
+ *quotient_ret = 1;
+ *remainder_ret = 0;
+ return;
+ }
+
+ uint128 denominator = divisor;
+ uint128 position = 1;
+ uint128 quotient = 0;
+
+ // Left aligns the MSB of the denominator and the dividend.
+ int shift = Fls128(dividend) - Fls128(denominator);
+ denominator <<= shift;
+ position <<= shift;
+
+ // Uses shift-subtract algorithm to divide dividend by denominator. The
+ // remainder will be left in dividend.
+ while (position > 0) {
+ if (dividend >= denominator) {
+ dividend -= denominator;
+ quotient |= position;
+ }
+ position >>= 1;
+ denominator >>= 1;
+ }
+
+ *quotient_ret = quotient;
+ *remainder_ret = dividend;
+}
+
+uint128& uint128::operator/=(const uint128& divisor) {
+ uint128 quotient = 0;
+ uint128 remainder = 0;
+ DivModImpl(*this, divisor, &quotient, &remainder);
+ *this = quotient;
+ return *this;
+}
+uint128& uint128::operator%=(const uint128& divisor) {
+ uint128 quotient = 0;
+ uint128 remainder = 0;
+ DivModImpl(*this, divisor, &quotient, &remainder);
+ *this = remainder;
+ return *this;
+}
+
+std::ostream& operator<<(std::ostream& o, const uint128& b) {
+ std::ios_base::fmtflags flags = o.flags();
+
+ // Select a divisor which is the largest power of the base < 2^64.
+ uint128 div;
+ std::streamsize div_base_log;
+ switch (flags & std::ios::basefield) {
+ case std::ios::hex:
+ div = GOOGLE_ULONGLONG(0x1000000000000000); // 16^15
+ div_base_log = 15;
+ break;
+ case std::ios::oct:
+ div = GOOGLE_ULONGLONG(01000000000000000000000); // 8^21
+ div_base_log = 21;
+ break;
+ default: // std::ios::dec
+ div = GOOGLE_ULONGLONG(10000000000000000000); // 10^19
+ div_base_log = 19;
+ break;
+ }
+
+ // Now piece together the uint128 representation from three chunks of
+ // the original value, each less than "div" and therefore representable
+ // as a uint64.
+ std::ostringstream os;
+ std::ios_base::fmtflags copy_mask =
+ std::ios::basefield | std::ios::showbase | std::ios::uppercase;
+ os.setf(flags & copy_mask, copy_mask);
+ uint128 high = b;
+ uint128 low;
+ uint128::DivModImpl(high, div, &high, &low);
+ uint128 mid;
+ uint128::DivModImpl(high, div, &high, &mid);
+ if (high.lo_ != 0) {
+ os << high.lo_;
+ os << std::noshowbase << std::setfill('0') << std::setw(div_base_log);
+ os << mid.lo_;
+ os << std::setw(div_base_log);
+ } else if (mid.lo_ != 0) {
+ os << mid.lo_;
+ os << std::noshowbase << std::setfill('0') << std::setw(div_base_log);
+ }
+ os << low.lo_;
+ std::string rep = os.str();
+
+ // Add the requisite padding.
+ std::streamsize width = o.width(0);
+ if (width > rep.size()) {
+ if ((flags & std::ios::adjustfield) == std::ios::left) {
+ rep.append(width - rep.size(), o.fill());
+ } else {
+ rep.insert(0, width - rep.size(), o.fill());
+ }
+ }
+
+ // Stream the final representation in a single "<<" call.
+ return o << rep;
+}
+
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/int128.h b/src/google/protobuf/stubs/int128.h
new file mode 100644
index 00000000..1499bb76
--- /dev/null
+++ b/src/google/protobuf/stubs/int128.h
@@ -0,0 +1,383 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifndef GOOGLE_PROTOBUF_STUBS_INT128_H_
+#define GOOGLE_PROTOBUF_STUBS_INT128_H_
+
+#include <google/protobuf/stubs/common.h>
+
+#include <iosfwd>
+
+namespace google {
+namespace protobuf {
+
+struct uint128_pod;
+
+// TODO(xiaofeng): Define GOOGLE_PROTOBUF_HAS_CONSTEXPR when constexpr is
+// available.
+#ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR
+# define UINT128_CONSTEXPR constexpr
+#else
+# define UINT128_CONSTEXPR
+#endif
+
+// An unsigned 128-bit integer type. Thread-compatible.
+class LIBPROTOBUF_EXPORT uint128 {
+ public:
+ UINT128_CONSTEXPR uint128(); // Sets to 0, but don't trust on this behavior.
+ UINT128_CONSTEXPR uint128(uint64 top, uint64 bottom);
+#ifndef SWIG
+ UINT128_CONSTEXPR uint128(int bottom);
+ UINT128_CONSTEXPR uint128(uint32 bottom); // Top 96 bits = 0
+#endif
+ UINT128_CONSTEXPR uint128(uint64 bottom); // hi_ = 0
+ UINT128_CONSTEXPR uint128(const uint128_pod &val);
+
+ // Trivial copy constructor, assignment operator and destructor.
+
+ void Initialize(uint64 top, uint64 bottom);
+
+ // Arithmetic operators.
+ uint128& operator+=(const uint128& b);
+ uint128& operator-=(const uint128& b);
+ uint128& operator*=(const uint128& b);
+ // Long division/modulo for uint128.
+ uint128& operator/=(const uint128& b);
+ uint128& operator%=(const uint128& b);
+ uint128 operator++(int);
+ uint128 operator--(int);
+ uint128& operator<<=(int);
+ uint128& operator>>=(int);
+ uint128& operator&=(const uint128& b);
+ uint128& operator|=(const uint128& b);
+ uint128& operator^=(const uint128& b);
+ uint128& operator++();
+ uint128& operator--();
+
+ friend uint64 Uint128Low64(const uint128& v);
+ friend uint64 Uint128High64(const uint128& v);
+
+ // We add "std::" to avoid including all of port.h.
+ LIBPROTOBUF_EXPORT friend std::ostream& operator<<(std::ostream& o,
+ const uint128& b);
+
+ private:
+ static void DivModImpl(uint128 dividend, uint128 divisor,
+ uint128* quotient_ret, uint128* remainder_ret);
+
+ // Little-endian memory order optimizations can benefit from
+ // having lo_ first, hi_ last.
+ // See util/endian/endian.h and Load128/Store128 for storing a uint128.
+ uint64 lo_;
+ uint64 hi_;
+
+ // Not implemented, just declared for catching automatic type conversions.
+ uint128(uint8);
+ uint128(uint16);
+ uint128(float v);
+ uint128(double v);
+};
+
+// This is a POD form of uint128 which can be used for static variables which
+// need to be operated on as uint128.
+struct uint128_pod {
+ // Note: The ordering of fields is different than 'class uint128' but the
+ // same as its 2-arg constructor. This enables more obvious initialization
+ // of static instances, which is the primary reason for this struct in the
+ // first place. This does not seem to defeat any optimizations wrt
+ // operations involving this struct.
+ uint64 hi;
+ uint64 lo;
+};
+
+LIBPROTOBUF_EXPORT extern const uint128_pod kuint128max;
+
+// allow uint128 to be logged
+LIBPROTOBUF_EXPORT extern std::ostream& operator<<(std::ostream& o,
+ const uint128& b);
+
+// Methods to access low and high pieces of 128-bit value.
+// Defined externally from uint128 to facilitate conversion
+// to native 128-bit types when compilers support them.
+inline uint64 Uint128Low64(const uint128& v) { return v.lo_; }
+inline uint64 Uint128High64(const uint128& v) { return v.hi_; }
+
+// TODO: perhaps it would be nice to have int128, a signed 128-bit type?
+
+// --------------------------------------------------------------------------
+// Implementation details follow
+// --------------------------------------------------------------------------
+inline bool operator==(const uint128& lhs, const uint128& rhs) {
+ return (Uint128Low64(lhs) == Uint128Low64(rhs) &&
+ Uint128High64(lhs) == Uint128High64(rhs));
+}
+inline bool operator!=(const uint128& lhs, const uint128& rhs) {
+ return !(lhs == rhs);
+}
+
+inline UINT128_CONSTEXPR uint128::uint128() : lo_(0), hi_(0) {}
+inline UINT128_CONSTEXPR uint128::uint128(uint64 top, uint64 bottom)
+ : lo_(bottom), hi_(top) {}
+inline UINT128_CONSTEXPR uint128::uint128(const uint128_pod& v)
+ : lo_(v.lo), hi_(v.hi) {}
+inline UINT128_CONSTEXPR uint128::uint128(uint64 bottom)
+ : lo_(bottom), hi_(0) {}
+#ifndef SWIG
+inline UINT128_CONSTEXPR uint128::uint128(uint32 bottom)
+ : lo_(bottom), hi_(0) {}
+inline UINT128_CONSTEXPR uint128::uint128(int bottom)
+ : lo_(bottom), hi_(static_cast<int64>((bottom < 0) ? -1 : 0)) {}
+#endif
+
+#undef UINT128_CONSTEXPR
+
+inline void uint128::Initialize(uint64 top, uint64 bottom) {
+ hi_ = top;
+ lo_ = bottom;
+}
+
+// Comparison operators.
+
+#define CMP128(op) \
+inline bool operator op(const uint128& lhs, const uint128& rhs) { \
+ return (Uint128High64(lhs) == Uint128High64(rhs)) ? \
+ (Uint128Low64(lhs) op Uint128Low64(rhs)) : \
+ (Uint128High64(lhs) op Uint128High64(rhs)); \
+}
+
+CMP128(<)
+CMP128(>)
+CMP128(>=)
+CMP128(<=)
+
+#undef CMP128
+
+// Unary operators
+
+inline uint128 operator-(const uint128& val) {
+ const uint64 hi_flip = ~Uint128High64(val);
+ const uint64 lo_flip = ~Uint128Low64(val);
+ const uint64 lo_add = lo_flip + 1;
+ if (lo_add < lo_flip) {
+ return uint128(hi_flip + 1, lo_add);
+ }
+ return uint128(hi_flip, lo_add);
+}
+
+inline bool operator!(const uint128& val) {
+ return !Uint128High64(val) && !Uint128Low64(val);
+}
+
+// Logical operators.
+
+inline uint128 operator~(const uint128& val) {
+ return uint128(~Uint128High64(val), ~Uint128Low64(val));
+}
+
+#define LOGIC128(op) \
+inline uint128 operator op(const uint128& lhs, const uint128& rhs) { \
+ return uint128(Uint128High64(lhs) op Uint128High64(rhs), \
+ Uint128Low64(lhs) op Uint128Low64(rhs)); \
+}
+
+LOGIC128(|)
+LOGIC128(&)
+LOGIC128(^)
+
+#undef LOGIC128
+
+#define LOGICASSIGN128(op) \
+inline uint128& uint128::operator op(const uint128& other) { \
+ hi_ op other.hi_; \
+ lo_ op other.lo_; \
+ return *this; \
+}
+
+LOGICASSIGN128(|=)
+LOGICASSIGN128(&=)
+LOGICASSIGN128(^=)
+
+#undef LOGICASSIGN128
+
+// Shift operators.
+
+inline uint128 operator<<(const uint128& val, int amount) {
+ // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
+ if (amount < 64) {
+ if (amount == 0) {
+ return val;
+ }
+ uint64 new_hi = (Uint128High64(val) << amount) |
+ (Uint128Low64(val) >> (64 - amount));
+ uint64 new_lo = Uint128Low64(val) << amount;
+ return uint128(new_hi, new_lo);
+ } else if (amount < 128) {
+ return uint128(Uint128Low64(val) << (amount - 64), 0);
+ } else {
+ return uint128(0, 0);
+ }
+}
+
+inline uint128 operator>>(const uint128& val, int amount) {
+ // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
+ if (amount < 64) {
+ if (amount == 0) {
+ return val;
+ }
+ uint64 new_hi = Uint128High64(val) >> amount;
+ uint64 new_lo = (Uint128Low64(val) >> amount) |
+ (Uint128High64(val) << (64 - amount));
+ return uint128(new_hi, new_lo);
+ } else if (amount < 128) {
+ return uint128(0, Uint128High64(val) >> (amount - 64));
+ } else {
+ return uint128(0, 0);
+ }
+}
+
+inline uint128& uint128::operator<<=(int amount) {
+ // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
+ if (amount < 64) {
+ if (amount != 0) {
+ hi_ = (hi_ << amount) | (lo_ >> (64 - amount));
+ lo_ = lo_ << amount;
+ }
+ } else if (amount < 128) {
+ hi_ = lo_ << (amount - 64);
+ lo_ = 0;
+ } else {
+ hi_ = 0;
+ lo_ = 0;
+ }
+ return *this;
+}
+
+inline uint128& uint128::operator>>=(int amount) {
+ // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
+ if (amount < 64) {
+ if (amount != 0) {
+ lo_ = (lo_ >> amount) | (hi_ << (64 - amount));
+ hi_ = hi_ >> amount;
+ }
+ } else if (amount < 128) {
+ lo_ = hi_ >> (amount - 64);
+ hi_ = 0;
+ } else {
+ lo_ = 0;
+ hi_ = 0;
+ }
+ return *this;
+}
+
+inline uint128 operator+(const uint128& lhs, const uint128& rhs) {
+ return uint128(lhs) += rhs;
+}
+
+inline uint128 operator-(const uint128& lhs, const uint128& rhs) {
+ return uint128(lhs) -= rhs;
+}
+
+inline uint128 operator*(const uint128& lhs, const uint128& rhs) {
+ return uint128(lhs) *= rhs;
+}
+
+inline uint128 operator/(const uint128& lhs, const uint128& rhs) {
+ return uint128(lhs) /= rhs;
+}
+
+inline uint128 operator%(const uint128& lhs, const uint128& rhs) {
+ return uint128(lhs) %= rhs;
+}
+
+inline uint128& uint128::operator+=(const uint128& b) {
+ hi_ += b.hi_;
+ uint64 lolo = lo_ + b.lo_;
+ if (lolo < lo_)
+ ++hi_;
+ lo_ = lolo;
+ return *this;
+}
+
+inline uint128& uint128::operator-=(const uint128& b) {
+ hi_ -= b.hi_;
+ if (b.lo_ > lo_)
+ --hi_;
+ lo_ -= b.lo_;
+ return *this;
+}
+
+inline uint128& uint128::operator*=(const uint128& b) {
+ uint64 a96 = hi_ >> 32;
+ uint64 a64 = hi_ & 0xffffffffu;
+ uint64 a32 = lo_ >> 32;
+ uint64 a00 = lo_ & 0xffffffffu;
+ uint64 b96 = b.hi_ >> 32;
+ uint64 b64 = b.hi_ & 0xffffffffu;
+ uint64 b32 = b.lo_ >> 32;
+ uint64 b00 = b.lo_ & 0xffffffffu;
+ // multiply [a96 .. a00] x [b96 .. b00]
+ // terms higher than c96 disappear off the high side
+ // terms c96 and c64 are safe to ignore carry bit
+ uint64 c96 = a96 * b00 + a64 * b32 + a32 * b64 + a00 * b96;
+ uint64 c64 = a64 * b00 + a32 * b32 + a00 * b64;
+ this->hi_ = (c96 << 32) + c64;
+ this->lo_ = 0;
+ // add terms after this one at a time to capture carry
+ *this += uint128(a32 * b00) << 32;
+ *this += uint128(a00 * b32) << 32;
+ *this += a00 * b00;
+ return *this;
+}
+
+inline uint128 uint128::operator++(int) {
+ uint128 tmp(*this);
+ *this += 1;
+ return tmp;
+}
+
+inline uint128 uint128::operator--(int) {
+ uint128 tmp(*this);
+ *this -= 1;
+ return tmp;
+}
+
+inline uint128& uint128::operator++() {
+ *this += 1;
+ return *this;
+}
+
+inline uint128& uint128::operator--() {
+ *this -= 1;
+ return *this;
+}
+
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_INT128_H_
diff --git a/src/google/protobuf/stubs/int128_unittest.cc b/src/google/protobuf/stubs/int128_unittest.cc
new file mode 100644
index 00000000..5d33292c
--- /dev/null
+++ b/src/google/protobuf/stubs/int128_unittest.cc
@@ -0,0 +1,513 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/stubs/int128.h>
+
+#include <algorithm>
+#include <sstream>
+#include <utility>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+
+TEST(Int128, AllTests) {
+ uint128 zero(0);
+ uint128 one(1);
+ uint128 one_2arg(0, 1);
+ uint128 two(0, 2);
+ uint128 three(0, 3);
+ uint128 big(2000, 2);
+ uint128 big_minus_one(2000, 1);
+ uint128 bigger(2001, 1);
+ uint128 biggest(kuint128max);
+ uint128 high_low(1, 0);
+ uint128 low_high(0, kuint64max);
+ EXPECT_LT(one, two);
+ EXPECT_GT(two, one);
+ EXPECT_LT(one, big);
+ EXPECT_LT(one, big);
+ EXPECT_EQ(one, one_2arg);
+ EXPECT_NE(one, two);
+ EXPECT_GT(big, one);
+ EXPECT_GE(big, two);
+ EXPECT_GE(big, big_minus_one);
+ EXPECT_GT(big, big_minus_one);
+ EXPECT_LT(big_minus_one, big);
+ EXPECT_LE(big_minus_one, big);
+ EXPECT_NE(big_minus_one, big);
+ EXPECT_LT(big, biggest);
+ EXPECT_LE(big, biggest);
+ EXPECT_GT(biggest, big);
+ EXPECT_GE(biggest, big);
+ EXPECT_EQ(big, ~~big);
+ EXPECT_EQ(one, one | one);
+ EXPECT_EQ(big, big | big);
+ EXPECT_EQ(one, one | zero);
+ EXPECT_EQ(one, one & one);
+ EXPECT_EQ(big, big & big);
+ EXPECT_EQ(zero, one & zero);
+ EXPECT_EQ(zero, big & ~big);
+ EXPECT_EQ(zero, one ^ one);
+ EXPECT_EQ(zero, big ^ big);
+ EXPECT_EQ(one, one ^ zero);
+
+ // Shift operators.
+ EXPECT_EQ(big, big << 0);
+ EXPECT_EQ(big, big >> 0);
+ EXPECT_GT(big << 1, big);
+ EXPECT_LT(big >> 1, big);
+ EXPECT_EQ(big, (big << 10) >> 10);
+ EXPECT_EQ(big, (big >> 1) << 1);
+ EXPECT_EQ(one, (one << 80) >> 80);
+ EXPECT_EQ(zero, (one >> 80) << 80);
+ EXPECT_EQ(zero, big >> 128);
+ EXPECT_EQ(zero, big << 128);
+
+ // Shift assignments.
+ uint128 big_copy = big;
+ EXPECT_EQ(big << 0, big_copy <<= 0);
+ big_copy = big;
+ EXPECT_EQ(big >> 0, big_copy >>= 0);
+ big_copy = big;
+ EXPECT_EQ(big << 1, big_copy <<= 1);
+ big_copy = big;
+ EXPECT_EQ(big >> 1, big_copy >>= 1);
+ big_copy = big;
+ EXPECT_EQ(big << 10, big_copy <<= 10);
+ big_copy = big;
+ EXPECT_EQ(big >> 10, big_copy >>= 10);
+ big_copy = big;
+ EXPECT_EQ(big << 64, big_copy <<= 64);
+ big_copy = big;
+ EXPECT_EQ(big >> 64, big_copy >>= 64);
+ big_copy = big;
+ EXPECT_EQ(big << 73, big_copy <<= 73);
+ big_copy = big;
+ EXPECT_EQ(big >> 73, big_copy >>= 73);
+ big_copy = big;
+ EXPECT_EQ(big << 128, big_copy <<= 128);
+ big_copy = big;
+ EXPECT_EQ(big >> 128, big_copy >>= 128);
+
+ EXPECT_EQ(Uint128High64(biggest), kuint64max);
+ EXPECT_EQ(Uint128Low64(biggest), kuint64max);
+ EXPECT_EQ(zero + one, one);
+ EXPECT_EQ(one + one, two);
+ EXPECT_EQ(big_minus_one + one, big);
+ EXPECT_EQ(one - one, zero);
+ EXPECT_EQ(one - zero, one);
+ EXPECT_EQ(zero - one, biggest);
+ EXPECT_EQ(big - big, zero);
+ EXPECT_EQ(big - one, big_minus_one);
+ EXPECT_EQ(big + kuint64max, bigger);
+ EXPECT_EQ(biggest + 1, zero);
+ EXPECT_EQ(zero - 1, biggest);
+ EXPECT_EQ(high_low - one, low_high);
+ EXPECT_EQ(low_high + one, high_low);
+ EXPECT_EQ(Uint128High64((uint128(1) << 64) - 1), 0);
+ EXPECT_EQ(Uint128Low64((uint128(1) << 64) - 1), kuint64max);
+ EXPECT_TRUE(!!one);
+ EXPECT_TRUE(!!high_low);
+ EXPECT_FALSE(!!zero);
+ EXPECT_FALSE(!one);
+ EXPECT_FALSE(!high_low);
+ EXPECT_TRUE(!zero);
+ EXPECT_TRUE(zero == 0);
+ EXPECT_FALSE(zero != 0);
+ EXPECT_FALSE(one == 0);
+ EXPECT_TRUE(one != 0);
+
+ uint128 test = zero;
+ EXPECT_EQ(++test, one);
+ EXPECT_EQ(test, one);
+ EXPECT_EQ(test++, one);
+ EXPECT_EQ(test, two);
+ EXPECT_EQ(test -= 2, zero);
+ EXPECT_EQ(test, zero);
+ EXPECT_EQ(test += 2, two);
+ EXPECT_EQ(test, two);
+ EXPECT_EQ(--test, one);
+ EXPECT_EQ(test, one);
+ EXPECT_EQ(test--, one);
+ EXPECT_EQ(test, zero);
+ EXPECT_EQ(test |= three, three);
+ EXPECT_EQ(test &= one, one);
+ EXPECT_EQ(test ^= three, two);
+ EXPECT_EQ(test >>= 1, one);
+ EXPECT_EQ(test <<= 1, two);
+
+ EXPECT_EQ(big, -(-big));
+ EXPECT_EQ(two, -((-one) - 1));
+ EXPECT_EQ(kuint128max, -one);
+ EXPECT_EQ(zero, -zero);
+
+ GOOGLE_LOG(INFO) << one;
+ GOOGLE_LOG(INFO) << big_minus_one;
+}
+
+TEST(Int128, PodTests) {
+ uint128_pod pod = { 12345, 67890 };
+ uint128 from_pod(pod);
+ EXPECT_EQ(12345, Uint128High64(from_pod));
+ EXPECT_EQ(67890, Uint128Low64(from_pod));
+
+ uint128 zero(0);
+ uint128_pod zero_pod = {0, 0};
+ uint128 one(1);
+ uint128_pod one_pod = {0, 1};
+ uint128 two(2);
+ uint128_pod two_pod = {0, 2};
+ uint128 three(3);
+ uint128_pod three_pod = {0, 3};
+ uint128 big(1, 0);
+ uint128_pod big_pod = {1, 0};
+
+ EXPECT_EQ(zero, zero_pod);
+ EXPECT_EQ(zero_pod, zero);
+ EXPECT_EQ(zero_pod, zero_pod);
+ EXPECT_EQ(one, one_pod);
+ EXPECT_EQ(one_pod, one);
+ EXPECT_EQ(one_pod, one_pod);
+ EXPECT_EQ(two, two_pod);
+ EXPECT_EQ(two_pod, two);
+ EXPECT_EQ(two_pod, two_pod);
+
+ EXPECT_NE(one, two_pod);
+ EXPECT_NE(one_pod, two);
+ EXPECT_NE(one_pod, two_pod);
+
+ EXPECT_LT(one, two_pod);
+ EXPECT_LT(one_pod, two);
+ EXPECT_LT(one_pod, two_pod);
+ EXPECT_LE(one, one_pod);
+ EXPECT_LE(one_pod, one);
+ EXPECT_LE(one_pod, one_pod);
+ EXPECT_LE(one, two_pod);
+ EXPECT_LE(one_pod, two);
+ EXPECT_LE(one_pod, two_pod);
+
+ EXPECT_GT(two, one_pod);
+ EXPECT_GT(two_pod, one);
+ EXPECT_GT(two_pod, one_pod);
+ EXPECT_GE(two, two_pod);
+ EXPECT_GE(two_pod, two);
+ EXPECT_GE(two_pod, two_pod);
+ EXPECT_GE(two, one_pod);
+ EXPECT_GE(two_pod, one);
+ EXPECT_GE(two_pod, one_pod);
+
+ EXPECT_EQ(three, one | two_pod);
+ EXPECT_EQ(three, one_pod | two);
+ EXPECT_EQ(three, one_pod | two_pod);
+ EXPECT_EQ(one, three & one_pod);
+ EXPECT_EQ(one, three_pod & one);
+ EXPECT_EQ(one, three_pod & one_pod);
+ EXPECT_EQ(two, three ^ one_pod);
+ EXPECT_EQ(two, three_pod ^ one);
+ EXPECT_EQ(two, three_pod ^ one_pod);
+ EXPECT_EQ(two, three & (~one));
+ EXPECT_EQ(three, ~~three);
+
+ EXPECT_EQ(two, two_pod << 0);
+ EXPECT_EQ(two, one_pod << 1);
+ EXPECT_EQ(big, one_pod << 64);
+ EXPECT_EQ(zero, one_pod << 128);
+ EXPECT_EQ(two, two_pod >> 0);
+ EXPECT_EQ(one, two_pod >> 1);
+ EXPECT_EQ(one, big_pod >> 64);
+
+ EXPECT_EQ(one, zero + one_pod);
+ EXPECT_EQ(one, zero_pod + one);
+ EXPECT_EQ(one, zero_pod + one_pod);
+ EXPECT_EQ(one, two - one_pod);
+ EXPECT_EQ(one, two_pod - one);
+ EXPECT_EQ(one, two_pod - one_pod);
+}
+
+TEST(Int128, OperatorAssignReturnRef) {
+ uint128 v(1);
+ (v += 4) -= 3;
+ EXPECT_EQ(2, v);
+}
+
+TEST(Int128, Multiply) {
+ uint128 a, b, c;
+
+ // Zero test.
+ a = 0;
+ b = 0;
+ c = a * b;
+ EXPECT_EQ(0, c);
+
+ // Max carries.
+ a = uint128(0) - 1;
+ b = uint128(0) - 1;
+ c = a * b;
+ EXPECT_EQ(1, c);
+
+ // Self-operation with max carries.
+ c = uint128(0) - 1;
+ c *= c;
+ EXPECT_EQ(1, c);
+
+ // 1-bit x 1-bit.
+ for (int i = 0; i < 64; ++i) {
+ for (int j = 0; j < 64; ++j) {
+ a = uint128(1) << i;
+ b = uint128(1) << j;
+ c = a * b;
+ EXPECT_EQ(uint128(1) << (i+j), c);
+ }
+ }
+
+ // Verified with dc.
+ a = uint128(GOOGLE_ULONGLONG(0xffffeeeeddddcccc),
+ GOOGLE_ULONGLONG(0xbbbbaaaa99998888));
+ b = uint128(GOOGLE_ULONGLONG(0x7777666655554444),
+ GOOGLE_ULONGLONG(0x3333222211110000));
+ c = a * b;
+ EXPECT_EQ(uint128(GOOGLE_ULONGLONG(0x530EDA741C71D4C3),
+ GOOGLE_ULONGLONG(0xBF25975319080000)), c);
+ EXPECT_EQ(0, c - b * a);
+ EXPECT_EQ(a*a - b*b, (a+b) * (a-b));
+
+ // Verified with dc.
+ a = uint128(GOOGLE_ULONGLONG(0x0123456789abcdef),
+ GOOGLE_ULONGLONG(0xfedcba9876543210));
+ b = uint128(GOOGLE_ULONGLONG(0x02468ace13579bdf),
+ GOOGLE_ULONGLONG(0xfdb97531eca86420));
+ c = a * b;
+ EXPECT_EQ(uint128(GOOGLE_ULONGLONG(0x97a87f4f261ba3f2),
+ GOOGLE_ULONGLONG(0x342d0bbf48948200)), c);
+ EXPECT_EQ(0, c - b * a);
+ EXPECT_EQ(a*a - b*b, (a+b) * (a-b));
+}
+
+TEST(Int128, AliasTests) {
+ uint128 x1(1, 2);
+ uint128 x2(2, 4);
+ x1 += x1;
+ EXPECT_EQ(x2, x1);
+
+ uint128 x3(1, static_cast<uint64>(1) << 63);
+ uint128 x4(3, 0);
+ x3 += x3;
+ EXPECT_EQ(x4, x3);
+}
+
+#ifdef PROTOBUF_HAS_DEATH_TEST
+TEST(Int128, DivideByZeroCheckFails) {
+ uint128 a = 0;
+ uint128 b = 0;
+ EXPECT_DEATH(a / b, "Division or mod by zero:");
+ a = 123;
+ EXPECT_DEATH(a / b, "Division or mod by zero:");
+}
+
+TEST(Int128, ModByZeroCheckFails) {
+ uint128 a = 0;
+ uint128 b = 0;
+ EXPECT_DEATH(a % b, "Division or mod by zero:");
+ a = 123;
+ EXPECT_DEATH(a % b, "Division or mod by zero:");
+}
+#endif // PROTOBUF_HAS_DEATH_TEST
+
+TEST(Int128, DivideAndMod) {
+ // a := q * b + r
+ uint128 a, b, q, r;
+
+ // Zero test.
+ a = 0;
+ b = 123;
+ q = a / b;
+ r = a % b;
+ EXPECT_EQ(0, q);
+ EXPECT_EQ(0, r);
+
+ a = uint128(GOOGLE_ULONGLONG(0x530eda741c71d4c3),
+ GOOGLE_ULONGLONG(0xbf25975319080000));
+ q = uint128(GOOGLE_ULONGLONG(0x4de2cab081),
+ GOOGLE_ULONGLONG(0x14c34ab4676e4bab));
+ b = uint128(0x1110001);
+ r = uint128(0x3eb455);
+ ASSERT_EQ(a, q * b + r); // Sanity-check.
+
+ uint128 result_q, result_r;
+ result_q = a / b;
+ result_r = a % b;
+ EXPECT_EQ(q, result_q);
+ EXPECT_EQ(r, result_r);
+
+ // Try the other way around.
+ swap(q, b);
+ result_q = a / b;
+ result_r = a % b;
+ EXPECT_EQ(q, result_q);
+ EXPECT_EQ(r, result_r);
+ // Restore.
+ swap(b, q);
+
+ // Dividend < divisor; result should be q:0 r:<dividend>.
+ swap(a, b);
+ result_q = a / b;
+ result_r = a % b;
+ EXPECT_EQ(0, result_q);
+ EXPECT_EQ(a, result_r);
+ // Try the other way around.
+ swap(a, q);
+ result_q = a / b;
+ result_r = a % b;
+ EXPECT_EQ(0, result_q);
+ EXPECT_EQ(a, result_r);
+ // Restore.
+ swap(q, a);
+ swap(b, a);
+
+ // Try a large remainder.
+ b = a / 2 + 1;
+ uint128 expected_r(GOOGLE_ULONGLONG(0x29876d3a0e38ea61),
+ GOOGLE_ULONGLONG(0xdf92cba98c83ffff));
+ // Sanity checks.
+ ASSERT_EQ(a / 2 - 1, expected_r);
+ ASSERT_EQ(a, b + expected_r);
+ result_q = a / b;
+ result_r = a % b;
+ EXPECT_EQ(1, result_q);
+ EXPECT_EQ(expected_r, result_r);
+}
+
+static uint64 RandomUint64() {
+ uint64 v1 = rand();
+ uint64 v2 = rand();
+ uint64 v3 = rand();
+ return v1 * v2 + v3;
+}
+
+TEST(Int128, DivideAndModRandomInputs) {
+ const int kNumIters = 1 << 18;
+ for (int i = 0; i < kNumIters; ++i) {
+ const uint128 a(RandomUint64(), RandomUint64());
+ const uint128 b(RandomUint64(), RandomUint64());
+ if (b == 0) {
+ continue; // Avoid a div-by-zero.
+ }
+ const uint128 q = a / b;
+ const uint128 r = a % b;
+ ASSERT_EQ(a, b * q + r);
+ }
+}
+
+#ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR
+TEST(Int128, ConstexprTest) {
+ constexpr uint128 zero;
+ constexpr uint128 one = 1;
+ constexpr uint128_pod pod = {2, 3};
+ constexpr uint128 from_pod = pod;
+ constexpr uint128 minus_two = -2;
+ EXPECT_EQ(one, uint128(1));
+ EXPECT_EQ(from_pod, uint128(2, 3));
+ EXPECT_EQ(minus_two, uint128(-1ULL, -2ULL));
+}
+
+TEST(Int128, Traits) {
+ EXPECT_TRUE(std::is_trivially_copy_constructible<uint128>::value);
+ EXPECT_TRUE(std::is_trivially_copy_assignable<uint128>::value);
+ EXPECT_TRUE(std::is_trivially_destructible<uint128>::value);
+}
+#endif // GOOGLE_PROTOBUF_HAS_CONSTEXPR
+
+TEST(Int128, OStream) {
+ struct {
+ uint128 val;
+ std::ios_base::fmtflags flags;
+ std::streamsize width;
+ char fill;
+ const char* rep;
+ } cases[] = {
+ // zero with different bases
+ {uint128(0), std::ios::dec, 0, '_', "0"},
+ {uint128(0), std::ios::oct, 0, '_', "0"},
+ {uint128(0), std::ios::hex, 0, '_', "0"},
+ // crossover between lo_ and hi_
+ {uint128(0, -1), std::ios::dec, 0, '_', "18446744073709551615"},
+ {uint128(0, -1), std::ios::oct, 0, '_', "1777777777777777777777"},
+ {uint128(0, -1), std::ios::hex, 0, '_', "ffffffffffffffff"},
+ {uint128(1, 0), std::ios::dec, 0, '_', "18446744073709551616"},
+ {uint128(1, 0), std::ios::oct, 0, '_', "2000000000000000000000"},
+ {uint128(1, 0), std::ios::hex, 0, '_', "10000000000000000"},
+ // just the top bit
+ {uint128(GOOGLE_ULONGLONG(0x8000000000000000), 0), std::ios::dec, 0, '_',
+ "170141183460469231731687303715884105728"},
+ {uint128(GOOGLE_ULONGLONG(0x8000000000000000), 0), std::ios::oct, 0, '_',
+ "2000000000000000000000000000000000000000000"},
+ {uint128(GOOGLE_ULONGLONG(0x8000000000000000), 0), std::ios::hex, 0, '_',
+ "80000000000000000000000000000000"},
+ // maximum uint128 value
+ {uint128(-1, -1), std::ios::dec, 0, '_',
+ "340282366920938463463374607431768211455"},
+ {uint128(-1, -1), std::ios::oct, 0, '_',
+ "3777777777777777777777777777777777777777777"},
+ {uint128(-1, -1), std::ios::hex, 0, '_',
+ "ffffffffffffffffffffffffffffffff"},
+ // uppercase
+ {uint128(-1, -1), std::ios::hex | std::ios::uppercase, 0, '_',
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"},
+ // showbase
+ {uint128(1), std::ios::dec | std::ios::showbase, 0, '_', "1"},
+ {uint128(1), std::ios::oct | std::ios::showbase, 0, '_', "01"},
+ {uint128(1), std::ios::hex | std::ios::showbase, 0, '_', "0x1"},
+ // showbase does nothing on zero
+ {uint128(0), std::ios::dec | std::ios::showbase, 0, '_', "0"},
+ {uint128(0), std::ios::oct | std::ios::showbase, 0, '_', "0"},
+ {uint128(0), std::ios::hex | std::ios::showbase, 0, '_', "0"},
+ // showpos does nothing on unsigned types
+ {uint128(1), std::ios::dec | std::ios::showpos, 0, '_', "1"},
+ // padding
+ {uint128(9), std::ios::dec, 6, '_', "_____9"},
+ {uint128(12345), std::ios::dec, 6, '_', "_12345"},
+ // left adjustment
+ {uint128(9), std::ios::dec | std::ios::left, 6, '_', "9_____"},
+ {uint128(12345), std::ios::dec | std::ios::left, 6, '_', "12345_"},
+ };
+ for (size_t i = 0; i < GOOGLE_ARRAYSIZE(cases); ++i) {
+ ostringstream os;
+ os.flags(cases[i].flags);
+ os.width(cases[i].width);
+ os.fill(cases[i].fill);
+ os << cases[i].val;
+ EXPECT_EQ(cases[i].rep, os.str());
+ }
+}
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/logging.h b/src/google/protobuf/stubs/logging.h
index 330d33d2..3108db8c 100644
--- a/src/google/protobuf/stubs/logging.h
+++ b/src/google/protobuf/stubs/logging.h
@@ -65,6 +65,7 @@ class StringPiece;
namespace util {
class Status;
}
+class uint128;
namespace internal {
class LogFinisher;
@@ -78,7 +79,7 @@ class LIBPROTOBUF_EXPORT LogMessage {
LogMessage& operator<<(const char* value);
LogMessage& operator<<(char value);
LogMessage& operator<<(int value);
- LogMessage& operator<<(unsigned int value);
+ LogMessage& operator<<(uint value);
LogMessage& operator<<(long value);
LogMessage& operator<<(unsigned long value);
LogMessage& operator<<(long long value);
@@ -87,6 +88,7 @@ class LIBPROTOBUF_EXPORT LogMessage {
LogMessage& operator<<(void* value);
LogMessage& operator<<(const StringPiece& value);
LogMessage& operator<<(const ::google::protobuf::util::Status& status);
+ LogMessage& operator<<(const uint128& value);
private:
friend class LogFinisher;
diff --git a/src/google/protobuf/stubs/mathutil.h b/src/google/protobuf/stubs/mathutil.h
index 99c4d452..3a1ef8a8 100644
--- a/src/google/protobuf/stubs/mathutil.h
+++ b/src/google/protobuf/stubs/mathutil.h
@@ -45,9 +45,21 @@ bool IsNan(T value) {
return false;
}
template<>
-inline bool IsNan(float value) { return isnan(value); }
+inline bool IsNan(float value) {
+#ifdef _MSC_VER
+ return _isnan(value);
+#else
+ return isnan(value);
+#endif
+}
template<>
-inline bool IsNan(double value) { return isnan(value); }
+inline bool IsNan(double value) {
+#ifdef _MSC_VER
+ return _isnan(value);
+#else
+ return isnan(value);
+#endif
+}
template<typename T>
bool AlmostEquals(T a, T b) {
diff --git a/src/google/protobuf/stubs/port.h b/src/google/protobuf/stubs/port.h
index 74bdfffa..b35a3afe 100644
--- a/src/google/protobuf/stubs/port.h
+++ b/src/google/protobuf/stubs/port.h
@@ -45,12 +45,15 @@
#endif
#undef PROTOBUF_LITTLE_ENDIAN
-#ifdef _MSC_VER
+#ifdef _WIN32
// Assuming windows is always little-endian.
+ // TODO(xiaofeng): The PROTOBUF_LITTLE_ENDIAN is not only used for
+ // optimization but also for correctness. We should define an
+ // different macro to test the big-endian code path in coded_stream.
#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
#define PROTOBUF_LITTLE_ENDIAN 1
#endif
- #if _MSC_VER >= 1300
+ #if defined(_MSC_VER) && _MSC_VER >= 1300
// If MSVC has "/RTCc" set, it will complain about truncating casts at
// runtime. This file contains some intentional truncating casts.
#pragma runtime_checks("c", off)
@@ -109,20 +112,12 @@ typedef unsigned __int64 uint64;
typedef signed char int8;
typedef short int16;
typedef int int32;
-// NOTE: This should be "long long" for consistency with upstream, but
-// something is stacked against this particular type for 64bit hashing.
-// Switching it causes an obvious missing hash function (with an unobvious
-// cause) when building the tests.
-typedef int64_t int64;
+typedef long long int64;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
-// NOTE: This should be "unsigned long long" for consistency with upstream, but
-// something is stacked against this particular type for 64bit hashing.
-// Switching it causes an obvious missing hash function (with an unobvious
-// cause) when building the tests.
-typedef uint64_t uint64;
+typedef unsigned long long uint64;
#endif
// long long macros to be used because gcc and vc++ use different suffixes,
diff --git a/src/google/protobuf/stubs/status.cc b/src/google/protobuf/stubs/status.cc
index 7314c563..dd1bd614 100644
--- a/src/google/protobuf/stubs/status.cc
+++ b/src/google/protobuf/stubs/status.cc
@@ -30,7 +30,6 @@
#include <google/protobuf/stubs/status.h>
#include <ostream>
-#include <stdint.h>
#include <stdio.h>
#include <string>
#include <utility>
diff --git a/src/google/protobuf/stubs/structurally_valid.cc b/src/google/protobuf/stubs/structurally_valid.cc
index 0f6afe6d..d79a6ee4 100644
--- a/src/google/protobuf/stubs/structurally_valid.cc
+++ b/src/google/protobuf/stubs/structurally_valid.cc
@@ -3,6 +3,8 @@
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
+
namespace google {
namespace protobuf {
namespace internal {
@@ -531,6 +533,56 @@ bool IsStructurallyValidUTF8(const char* buf, int len) {
return (bytes_consumed == len);
}
+int UTF8SpnStructurallyValid(const StringPiece& str) {
+ if (!module_initialized_) return str.size();
+
+ int bytes_consumed = 0;
+ UTF8GenericScanFastAscii(&utf8acceptnonsurrogates_obj,
+ str.data(), str.size(), &bytes_consumed);
+ return bytes_consumed;
+}
+
+// Coerce UTF-8 byte string in src_str to be
+// a structurally-valid equal-length string by selectively
+// overwriting illegal bytes with replace_char (typically blank).
+// replace_char must be legal printable 7-bit Ascii 0x20..0x7e.
+// src_str is read-only. If any overwriting is needed, a modified byte string
+// is created in idst, length isrclen.
+//
+// Returns pointer to output buffer, isrc if no changes were made,
+// or idst if some bytes were changed.
+//
+// Fast case: all is structurally valid and no byte copying is done.
+//
+char* UTF8CoerceToStructurallyValid(const StringPiece& src_str,
+ char* idst,
+ const char replace_char) {
+ const char* isrc = src_str.data();
+ const int len = src_str.length();
+ int n = UTF8SpnStructurallyValid(src_str);
+ if (n == len) { // Normal case -- all is cool, return
+ return const_cast<char*>(isrc);
+ } else { // Unusual case -- copy w/o bad bytes
+ const char* src = isrc;
+ const char* srclimit = isrc + len;
+ char* dst = idst;
+ memmove(dst, src, n); // Copy initial good chunk
+ src += n;
+ dst += n;
+ while (src < srclimit) { // src points to bogus byte or is off the end
+ dst[0] = replace_char; // replace one bad byte
+ src++;
+ dst++;
+ StringPiece str2(src, srclimit - src);
+ n = UTF8SpnStructurallyValid(str2); // scan the remainder
+ memmove(dst, src, n); // copy next good chunk
+ src += n;
+ dst += n;
+ }
+ }
+ return idst;
+}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/test_util.cc b/src/google/protobuf/test_util.cc
index be1c90e0..07aa1d77 100644
--- a/src/google/protobuf/test_util.cc
+++ b/src/google/protobuf/test_util.cc
@@ -42,6 +42,7 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/test_util_lite.cc b/src/google/protobuf/test_util_lite.cc
index 88eca0ad..388c0cbd 100644
--- a/src/google/protobuf/test_util_lite.cc
+++ b/src/google/protobuf/test_util_lite.cc
@@ -33,6 +33,7 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/test_util_lite.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
diff --git a/src/google/protobuf/testing/googletest.cc b/src/google/protobuf/testing/googletest.cc
index b8bd790b..2b9cddef 100644
--- a/src/google/protobuf/testing/googletest.cc
+++ b/src/google/protobuf/testing/googletest.cc
@@ -94,6 +94,13 @@ string TestSourceDir() {
namespace {
string GetTemporaryDirectoryName() {
+ // Tests run under Bazel "should not" use /tmp. Bazel sets this environment
+ // variable for tests to use instead.
+ char *from_environment = getenv("TEST_TMPDIR");
+ if (from_environment != NULL && from_environment[0] != '\0') {
+ return string(from_environment) + "/protobuf_tmpdir";
+ }
+
// tmpnam() is generally not considered safe but we're only using it for
// testing. We cannot use tmpfile() or mkstemp() since we're creating a
// directory.
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index 76ce9875..1aafd8e6 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -38,11 +38,13 @@
#include <stdlib.h>
#include <limits>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.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>
+#include <google/protobuf/unittest_mset_wire_format.pb.h>
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/strutil.h>
diff --git a/src/google/protobuf/timestamp.proto b/src/google/protobuf/timestamp.proto
index 11f258da..06b60e6f 100644
--- a/src/google/protobuf/timestamp.proto
+++ b/src/google/protobuf/timestamp.proto
@@ -38,7 +38,6 @@ option java_package = "com.google.protobuf";
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
option objc_class_prefix = "GPB";
-
// A Timestamp represents a point in time independent of any time zone
// or calendar, represented as seconds and fractions of seconds at
// nanosecond resolution in UTC Epoch time. It is encoded using the
@@ -85,14 +84,16 @@ option objc_class_prefix = "GPB";
// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
// .setNanos((int) ((millis % 1000) * 1000000)).build();
//
-// Example 5: Compute Timestamp from Python `datetime.datetime`.
//
-// now = datetime.datetime.utcnow()
-// seconds = int(time.mktime(now.timetuple()))
-// nanos = now.microsecond * 1000
+// Example 5: Compute Timestamp from current time in Python.
+//
+// now = time.time()
+// seconds = int(now)
+// nanos = int((now - seconds) * 10**9)
// timestamp = Timestamp(seconds=seconds, nanos=nanos)
//
message Timestamp {
+
// Represents seconds of UTC time since Unix epoch
// 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to
// 9999-12-31T23:59:59Z inclusive.
diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc
index 029a72c6..8f993561 100644
--- a/src/google/protobuf/type.pb.cc
+++ b/src/google/protobuf/type.pb.cc
@@ -38,6 +38,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
const ::google::protobuf::Descriptor* Option_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
Option_reflection_ = NULL;
+const ::google::protobuf::EnumDescriptor* Syntax_descriptor_ = NULL;
} // namespace
@@ -49,12 +50,13 @@ void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto() {
"google/protobuf/type.proto");
GOOGLE_CHECK(file != NULL);
Type_descriptor_ = file->message_type(0);
- static const int Type_offsets_[5] = {
+ static const int Type_offsets_[6] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, fields_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, oneofs_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, options_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, source_context_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, syntax_),
};
Type_reflection_ =
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
@@ -68,7 +70,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, _internal_metadata_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, _is_default_instance_));
Field_descriptor_ = file->message_type(1);
- static const int Field_offsets_[8] = {
+ static const int Field_offsets_[9] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, kind_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, cardinality_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, number_),
@@ -77,6 +79,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, oneof_index_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, packed_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, options_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, json_name_),
};
Field_reflection_ =
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
@@ -92,11 +95,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto() {
Field_Kind_descriptor_ = Field_descriptor_->enum_type(0);
Field_Cardinality_descriptor_ = Field_descriptor_->enum_type(1);
Enum_descriptor_ = file->message_type(2);
- static const int Enum_offsets_[4] = {
+ static const int Enum_offsets_[5] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, enumvalue_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, options_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, source_context_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, syntax_),
};
Enum_reflection_ =
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
@@ -142,6 +146,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto() {
sizeof(Option),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Option, _internal_metadata_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Option, _is_default_instance_));
+ Syntax_descriptor_ = file->enum_type(0);
}
namespace {
@@ -192,38 +197,43 @@ void protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto() {
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n\032google/protobuf/type.proto\022\017google.pro"
"tobuf\032\031google/protobuf/any.proto\032$google"
- "/protobuf/source_context.proto\"\256\001\n\004Type\022"
+ "/protobuf/source_context.proto\"\327\001\n\004Type\022"
"\014\n\004name\030\001 \001(\t\022&\n\006fields\030\002 \003(\0132\026.google.p"
"rotobuf.Field\022\016\n\006oneofs\030\003 \003(\t\022(\n\007options"
"\030\004 \003(\0132\027.google.protobuf.Option\0226\n\016sourc"
"e_context\030\005 \001(\0132\036.google.protobuf.Source"
- "Context\"\233\005\n\005Field\022)\n\004kind\030\001 \001(\0162\033.google"
- ".protobuf.Field.Kind\0227\n\013cardinality\030\002 \001("
- "\0162\".google.protobuf.Field.Cardinality\022\016\n"
- "\006number\030\003 \001(\005\022\014\n\004name\030\004 \001(\t\022\020\n\010type_url\030"
- "\006 \001(\t\022\023\n\013oneof_index\030\007 \001(\005\022\016\n\006packed\030\010 \001"
- "(\010\022(\n\007options\030\t \003(\0132\027.google.protobuf.Op"
- "tion\"\270\002\n\004Kind\022\020\n\014TYPE_UNKNOWN\020\000\022\017\n\013TYPE_"
- "DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003"
- "\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYP"
- "E_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_BO"
- "OL\020\010\022\017\n\013TYPE_STRING\020\t\022\020\n\014TYPE_MESSAGE\020\013\022"
- "\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE"
- "_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rTYPE_SFIXE"
- "D64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_SINT64\020\022\""
- "t\n\013Cardinality\022\027\n\023CARDINALITY_UNKNOWN\020\000\022"
- "\030\n\024CARDINALITY_OPTIONAL\020\001\022\030\n\024CARDINALITY"
- "_REQUIRED\020\002\022\030\n\024CARDINALITY_REPEATED\020\003\"\245\001"
- "\n\004Enum\022\014\n\004name\030\001 \001(\t\022-\n\tenumvalue\030\002 \003(\0132"
- "\032.google.protobuf.EnumValue\022(\n\007options\030\003"
- " \003(\0132\027.google.protobuf.Option\0226\n\016source_"
- "context\030\004 \001(\0132\036.google.protobuf.SourceCo"
- "ntext\"S\n\tEnumValue\022\014\n\004name\030\001 \001(\t\022\016\n\006numb"
- "er\030\002 \001(\005\022(\n\007options\030\003 \003(\0132\027.google.proto"
- "buf.Option\";\n\006Option\022\014\n\004name\030\001 \001(\t\022#\n\005va"
- "lue\030\002 \001(\0132\024.google.protobuf.AnyBI\n\023com.g"
- "oogle.protobufB\tTypeProtoP\001\242\002\003GPB\252\002\036Goog"
- "le.Protobuf.WellKnownTypesb\006proto3", 1354);
+ "Context\022\'\n\006syntax\030\006 \001(\0162\027.google.protobu"
+ "f.Syntax\"\276\005\n\005Field\022)\n\004kind\030\001 \001(\0162\033.googl"
+ "e.protobuf.Field.Kind\0227\n\013cardinality\030\002 \001"
+ "(\0162\".google.protobuf.Field.Cardinality\022\016"
+ "\n\006number\030\003 \001(\005\022\014\n\004name\030\004 \001(\t\022\020\n\010type_url"
+ "\030\006 \001(\t\022\023\n\013oneof_index\030\007 \001(\005\022\016\n\006packed\030\010 "
+ "\001(\010\022(\n\007options\030\t \003(\0132\027.google.protobuf.O"
+ "ption\022\021\n\tjson_name\030\n \001(\t\"\310\002\n\004Kind\022\020\n\014TYP"
+ "E_UNKNOWN\020\000\022\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FLO"
+ "AT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n"
+ "\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE_"
+ "FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING\020"
+ "\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\nT"
+ "YPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_ENU"
+ "M\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rTYPE_SFIXED64\020"
+ "\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_SINT64\020\022\"t\n\013C"
+ "ardinality\022\027\n\023CARDINALITY_UNKNOWN\020\000\022\030\n\024C"
+ "ARDINALITY_OPTIONAL\020\001\022\030\n\024CARDINALITY_REQ"
+ "UIRED\020\002\022\030\n\024CARDINALITY_REPEATED\020\003\"\316\001\n\004En"
+ "um\022\014\n\004name\030\001 \001(\t\022-\n\tenumvalue\030\002 \003(\0132\032.go"
+ "ogle.protobuf.EnumValue\022(\n\007options\030\003 \003(\013"
+ "2\027.google.protobuf.Option\0226\n\016source_cont"
+ "ext\030\004 \001(\0132\036.google.protobuf.SourceContex"
+ "t\022\'\n\006syntax\030\005 \001(\0162\027.google.protobuf.Synt"
+ "ax\"S\n\tEnumValue\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030"
+ "\002 \001(\005\022(\n\007options\030\003 \003(\0132\027.google.protobuf"
+ ".Option\";\n\006Option\022\014\n\004name\030\001 \001(\t\022#\n\005value"
+ "\030\002 \001(\0132\024.google.protobuf.Any*.\n\006Syntax\022\021"
+ "\n\rSYNTAX_PROTO2\020\000\022\021\n\rSYNTAX_PROTO3\020\001BL\n\023"
+ "com.google.protobufB\tTypeProtoP\001\240\001\001\242\002\003GP"
+ "B\252\002\036Google.Protobuf.WellKnownTypesb\006prot"
+ "o3", 1522);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/type.proto", &protobuf_RegisterTypes);
Type::default_instance_ = new Type();
@@ -245,6 +255,20 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2ftype_2eproto {
protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
}
} static_descriptor_initializer_google_2fprotobuf_2ftype_2eproto_;
+const ::google::protobuf::EnumDescriptor* Syntax_descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Syntax_descriptor_;
+}
+bool Syntax_IsValid(int value) {
+ switch(value) {
+ case 0:
+ case 1:
+ return true;
+ default:
+ return false;
+ }
+}
+
namespace {
@@ -264,6 +288,7 @@ const int Type::kFieldsFieldNumber;
const int Type::kOneofsFieldNumber;
const int Type::kOptionsFieldNumber;
const int Type::kSourceContextFieldNumber;
+const int Type::kSyntaxFieldNumber;
#endif // !_MSC_VER
Type::Type()
@@ -291,6 +316,7 @@ void Type::SharedCtor() {
_cached_size_ = 0;
name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
source_context_ = NULL;
+ syntax_ = 0;
}
Type::~Type() {
@@ -334,6 +360,7 @@ void Type::Clear() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
+ syntax_ = 0;
fields_.Clear();
oneofs_.Clear();
options_.Clear();
@@ -354,10 +381,10 @@ bool Type::MergePartialFromCodedStream(
if (tag == 10) {
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_name()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.Type.name");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Type.name"));
} else {
goto handle_unusual;
}
@@ -388,11 +415,11 @@ bool Type::MergePartialFromCodedStream(
parse_oneofs:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->add_oneofs()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->oneofs(this->oneofs_size() - 1).data(),
this->oneofs(this->oneofs_size() - 1).length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.Type.oneofs");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Type.oneofs"));
} else {
goto handle_unusual;
}
@@ -427,6 +454,22 @@ bool Type::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
+ if (input->ExpectTag(48)) goto parse_syntax;
+ break;
+ }
+
+ // optional .google.protobuf.Syntax syntax = 6;
+ case 6: {
+ if (tag == 48) {
+ parse_syntax:
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ set_syntax(static_cast< ::google::protobuf::Syntax >(value));
+ } else {
+ goto handle_unusual;
+ }
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -457,9 +500,9 @@ void Type::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_start:google.protobuf.Type)
// optional string name = 1;
if (this->name().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Type.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
@@ -473,10 +516,10 @@ void Type::SerializeWithCachedSizes(
// repeated string oneofs = 3;
for (int i = 0; i < this->oneofs_size(); i++) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
- this->oneofs(i).data(), this->oneofs(i).length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
- "google.protobuf.Type.oneofs");
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+ this->oneofs(i).data(), this->oneofs(i).length(),
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+ "google.protobuf.Type.oneofs");
::google::protobuf::internal::WireFormatLite::WriteString(
3, this->oneofs(i), output);
}
@@ -493,6 +536,12 @@ void Type::SerializeWithCachedSizes(
5, *this->source_context_, output);
}
+ // optional .google.protobuf.Syntax syntax = 6;
+ if (this->syntax() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteEnum(
+ 6, this->syntax(), output);
+ }
+
// @@protoc_insertion_point(serialize_end:google.protobuf.Type)
}
@@ -501,9 +550,9 @@ void Type::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Type)
// optional string name = 1;
if (this->name().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Type.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
@@ -519,9 +568,9 @@ void Type::SerializeWithCachedSizes(
// repeated string oneofs = 3;
for (int i = 0; i < this->oneofs_size(); i++) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->oneofs(i).data(), this->oneofs(i).length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Type.oneofs");
target = ::google::protobuf::internal::WireFormatLite::
WriteStringToArray(3, this->oneofs(i), target);
@@ -541,6 +590,12 @@ void Type::SerializeWithCachedSizes(
5, *this->source_context_, target);
}
+ // optional .google.protobuf.Syntax syntax = 6;
+ if (this->syntax() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+ 6, this->syntax(), target);
+ }
+
// @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Type)
return target;
}
@@ -562,6 +617,12 @@ int Type::ByteSize() const {
*this->source_context_);
}
+ // optional .google.protobuf.Syntax syntax = 6;
+ if (this->syntax() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::EnumSize(this->syntax());
+ }
+
// repeated .google.protobuf.Field fields = 2;
total_size += 1 * this->fields_size();
for (int i = 0; i < this->fields_size(); i++) {
@@ -615,6 +676,9 @@ void Type::MergeFrom(const Type& from) {
if (from.has_source_context()) {
mutable_source_context()->::google::protobuf::SourceContext::MergeFrom(from.source_context());
}
+ if (from.syntax() != 0) {
+ set_syntax(from.syntax());
+ }
}
void Type::CopyFrom(const ::google::protobuf::Message& from) {
@@ -644,6 +708,7 @@ void Type::InternalSwap(Type* other) {
oneofs_.UnsafeArenaSwap(&other->oneofs_);
options_.UnsafeArenaSwap(&other->options_);
std::swap(source_context_, other->source_context_);
+ std::swap(syntax_, other->syntax_);
_internal_metadata_.Swap(&other->_internal_metadata_);
std::swap(_cached_size_, other->_cached_size_);
}
@@ -709,28 +774,28 @@ int Type::fields_size() const {
void Type::clear_fields() {
fields_.Clear();
}
- const ::google::protobuf::Field& Type::fields(int index) const {
+const ::google::protobuf::Field& Type::fields(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.Type.fields)
return fields_.Get(index);
}
- ::google::protobuf::Field* Type::mutable_fields(int index) {
+::google::protobuf::Field* Type::mutable_fields(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.Type.fields)
return fields_.Mutable(index);
}
- ::google::protobuf::Field* Type::add_fields() {
+::google::protobuf::Field* Type::add_fields() {
// @@protoc_insertion_point(field_add:google.protobuf.Type.fields)
return fields_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >&
-Type::fields() const {
- // @@protoc_insertion_point(field_list:google.protobuf.Type.fields)
- return fields_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >*
Type::mutable_fields() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.fields)
return &fields_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >&
+Type::fields() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Type.fields)
+ return fields_;
+}
// repeated string oneofs = 3;
int Type::oneofs_size() const {
@@ -793,28 +858,28 @@ int Type::options_size() const {
void Type::clear_options() {
options_.Clear();
}
- const ::google::protobuf::Option& Type::options(int index) const {
+const ::google::protobuf::Option& Type::options(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.Type.options)
return options_.Get(index);
}
- ::google::protobuf::Option* Type::mutable_options(int index) {
+::google::protobuf::Option* Type::mutable_options(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.Type.options)
return options_.Mutable(index);
}
- ::google::protobuf::Option* Type::add_options() {
+::google::protobuf::Option* Type::add_options() {
// @@protoc_insertion_point(field_add:google.protobuf.Type.options)
return options_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
-Type::options() const {
- // @@protoc_insertion_point(field_list:google.protobuf.Type.options)
- return options_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
Type::mutable_options() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.options)
return &options_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Type::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Type.options)
+ return options_;
+}
// optional .google.protobuf.SourceContext source_context = 5;
bool Type::has_source_context() const {
@@ -824,11 +889,11 @@ void Type::clear_source_context() {
if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
}
- const ::google::protobuf::SourceContext& Type::source_context() const {
+const ::google::protobuf::SourceContext& Type::source_context() const {
// @@protoc_insertion_point(field_get:google.protobuf.Type.source_context)
return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
}
- ::google::protobuf::SourceContext* Type::mutable_source_context() {
+::google::protobuf::SourceContext* Type::mutable_source_context() {
if (source_context_ == NULL) {
source_context_ = new ::google::protobuf::SourceContext;
@@ -836,13 +901,13 @@ void Type::clear_source_context() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Type.source_context)
return source_context_;
}
- ::google::protobuf::SourceContext* Type::release_source_context() {
+::google::protobuf::SourceContext* Type::release_source_context() {
::google::protobuf::SourceContext* temp = source_context_;
source_context_ = NULL;
return temp;
}
- void Type::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
+void Type::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
delete source_context_;
source_context_ = source_context;
if (source_context) {
@@ -853,6 +918,20 @@ void Type::clear_source_context() {
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Type.source_context)
}
+// optional .google.protobuf.Syntax syntax = 6;
+void Type::clear_syntax() {
+ syntax_ = 0;
+}
+ ::google::protobuf::Syntax Type::syntax() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Type.syntax)
+ return static_cast< ::google::protobuf::Syntax >(syntax_);
+}
+ void Type::set_syntax(::google::protobuf::Syntax value) {
+
+ syntax_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Type.syntax)
+}
+
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -873,6 +952,7 @@ bool Field_Kind_IsValid(int value) {
case 7:
case 8:
case 9:
+ case 10:
case 11:
case 12:
case 13:
@@ -898,6 +978,7 @@ const Field_Kind Field::TYPE_FIXED64;
const Field_Kind Field::TYPE_FIXED32;
const Field_Kind Field::TYPE_BOOL;
const Field_Kind Field::TYPE_STRING;
+const Field_Kind Field::TYPE_GROUP;
const Field_Kind Field::TYPE_MESSAGE;
const Field_Kind Field::TYPE_BYTES;
const Field_Kind Field::TYPE_UINT32;
@@ -944,6 +1025,7 @@ const int Field::kTypeUrlFieldNumber;
const int Field::kOneofIndexFieldNumber;
const int Field::kPackedFieldNumber;
const int Field::kOptionsFieldNumber;
+const int Field::kJsonNameFieldNumber;
#endif // !_MSC_VER
Field::Field()
@@ -975,6 +1057,7 @@ void Field::SharedCtor() {
type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
oneof_index_ = 0;
packed_ = false;
+ json_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
Field::~Field() {
@@ -985,6 +1068,7 @@ Field::~Field() {
void Field::SharedDtor() {
name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
type_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ json_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (this != default_instance_) {
}
}
@@ -1028,6 +1112,7 @@ void Field::Clear() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
packed_ = false;
+ json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
#undef ZR_HELPER_
#undef ZR_
@@ -1097,10 +1182,10 @@ bool Field::MergePartialFromCodedStream(
parse_name:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_name()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.Field.name");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Field.name"));
} else {
goto handle_unusual;
}
@@ -1114,10 +1199,10 @@ bool Field::MergePartialFromCodedStream(
parse_type_url:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_type_url()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->type_url().data(), this->type_url().length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.Field.type_url");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Field.type_url"));
} else {
goto handle_unusual;
}
@@ -1168,6 +1253,23 @@ bool Field::MergePartialFromCodedStream(
}
if (input->ExpectTag(74)) goto parse_loop_options;
input->UnsafeDecrementRecursionDepth();
+ if (input->ExpectTag(82)) goto parse_json_name;
+ break;
+ }
+
+ // optional string json_name = 10;
+ case 10: {
+ if (tag == 82) {
+ parse_json_name:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_json_name()));
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+ this->json_name().data(), this->json_name().length(),
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Field.json_name"));
+ } else {
+ goto handle_unusual;
+ }
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -1215,9 +1317,9 @@ void Field::SerializeWithCachedSizes(
// optional string name = 4;
if (this->name().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Field.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
4, this->name(), output);
@@ -1225,9 +1327,9 @@ void Field::SerializeWithCachedSizes(
// optional string type_url = 6;
if (this->type_url().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->type_url().data(), this->type_url().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Field.type_url");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
6, this->type_url(), output);
@@ -1249,6 +1351,16 @@ void Field::SerializeWithCachedSizes(
9, this->options(i), output);
}
+ // optional string json_name = 10;
+ if (this->json_name().size() > 0) {
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+ this->json_name().data(), this->json_name().length(),
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+ "google.protobuf.Field.json_name");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 10, this->json_name(), output);
+ }
+
// @@protoc_insertion_point(serialize_end:google.protobuf.Field)
}
@@ -1274,9 +1386,9 @@ void Field::SerializeWithCachedSizes(
// optional string name = 4;
if (this->name().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Field.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
@@ -1285,9 +1397,9 @@ void Field::SerializeWithCachedSizes(
// optional string type_url = 6;
if (this->type_url().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->type_url().data(), this->type_url().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Field.type_url");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
@@ -1311,6 +1423,17 @@ void Field::SerializeWithCachedSizes(
9, this->options(i), target);
}
+ // optional string json_name = 10;
+ if (this->json_name().size() > 0) {
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+ this->json_name().data(), this->json_name().length(),
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+ "google.protobuf.Field.json_name");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 10, this->json_name(), target);
+ }
+
// @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Field)
return target;
}
@@ -1363,6 +1486,13 @@ int Field::ByteSize() const {
total_size += 1 + 1;
}
+ // optional string json_name = 10;
+ if (this->json_name().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->json_name());
+ }
+
// repeated .google.protobuf.Option options = 9;
total_size += 1 * this->options_size();
for (int i = 0; i < this->options_size(); i++) {
@@ -1415,6 +1545,10 @@ void Field::MergeFrom(const Field& from) {
if (from.packed() != 0) {
set_packed(from.packed());
}
+ if (from.json_name().size() > 0) {
+
+ json_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.json_name_);
+ }
}
void Field::CopyFrom(const ::google::protobuf::Message& from) {
@@ -1447,6 +1581,7 @@ void Field::InternalSwap(Field* other) {
std::swap(oneof_index_, other->oneof_index_);
std::swap(packed_, other->packed_);
options_.UnsafeArenaSwap(&other->options_);
+ json_name_.Swap(&other->json_name_);
_internal_metadata_.Swap(&other->_internal_metadata_);
std::swap(_cached_size_, other->_cached_size_);
}
@@ -1625,27 +1760,70 @@ int Field::options_size() const {
void Field::clear_options() {
options_.Clear();
}
- const ::google::protobuf::Option& Field::options(int index) const {
+const ::google::protobuf::Option& Field::options(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.Field.options)
return options_.Get(index);
}
- ::google::protobuf::Option* Field::mutable_options(int index) {
+::google::protobuf::Option* Field::mutable_options(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.Field.options)
return options_.Mutable(index);
}
- ::google::protobuf::Option* Field::add_options() {
+::google::protobuf::Option* Field::add_options() {
// @@protoc_insertion_point(field_add:google.protobuf.Field.options)
return options_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Field::mutable_options() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Field.options)
+ return &options_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
Field::options() const {
// @@protoc_insertion_point(field_list:google.protobuf.Field.options)
return options_;
}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
-Field::mutable_options() {
- // @@protoc_insertion_point(field_mutable_list:google.protobuf.Field.options)
- return &options_;
+
+// optional string json_name = 10;
+void Field::clear_json_name() {
+ json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Field::json_name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.json_name)
+ return json_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Field::set_json_name(const ::std::string& value) {
+
+ json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Field.json_name)
+}
+ void Field::set_json_name(const char* value) {
+
+ json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Field.json_name)
+}
+ void Field::set_json_name(const char* value, size_t size) {
+
+ json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.json_name)
+}
+ ::std::string* Field::mutable_json_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Field.json_name)
+ return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Field::release_json_name() {
+
+ return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Field::set_allocated_json_name(::std::string* json_name) {
+ if (json_name != NULL) {
+
+ } else {
+
+ }
+ json_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), json_name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.json_name)
}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -1657,6 +1835,7 @@ const int Enum::kNameFieldNumber;
const int Enum::kEnumvalueFieldNumber;
const int Enum::kOptionsFieldNumber;
const int Enum::kSourceContextFieldNumber;
+const int Enum::kSyntaxFieldNumber;
#endif // !_MSC_VER
Enum::Enum()
@@ -1684,6 +1863,7 @@ void Enum::SharedCtor() {
_cached_size_ = 0;
name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
source_context_ = NULL;
+ syntax_ = 0;
}
Enum::~Enum() {
@@ -1727,6 +1907,7 @@ void Enum::Clear() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
+ syntax_ = 0;
enumvalue_.Clear();
options_.Clear();
}
@@ -1746,10 +1927,10 @@ bool Enum::MergePartialFromCodedStream(
if (tag == 10) {
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_name()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.Enum.name");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Enum.name"));
} else {
goto handle_unusual;
}
@@ -1799,6 +1980,22 @@ bool Enum::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
+ if (input->ExpectTag(40)) goto parse_syntax;
+ break;
+ }
+
+ // optional .google.protobuf.Syntax syntax = 5;
+ case 5: {
+ if (tag == 40) {
+ parse_syntax:
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ set_syntax(static_cast< ::google::protobuf::Syntax >(value));
+ } else {
+ goto handle_unusual;
+ }
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -1829,9 +2026,9 @@ void Enum::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_start:google.protobuf.Enum)
// optional string name = 1;
if (this->name().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Enum.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
@@ -1855,6 +2052,12 @@ void Enum::SerializeWithCachedSizes(
4, *this->source_context_, output);
}
+ // optional .google.protobuf.Syntax syntax = 5;
+ if (this->syntax() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteEnum(
+ 5, this->syntax(), output);
+ }
+
// @@protoc_insertion_point(serialize_end:google.protobuf.Enum)
}
@@ -1863,9 +2066,9 @@ void Enum::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Enum)
// optional string name = 1;
if (this->name().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Enum.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
@@ -1893,6 +2096,12 @@ void Enum::SerializeWithCachedSizes(
4, *this->source_context_, target);
}
+ // optional .google.protobuf.Syntax syntax = 5;
+ if (this->syntax() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+ 5, this->syntax(), target);
+ }
+
// @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Enum)
return target;
}
@@ -1914,6 +2123,12 @@ int Enum::ByteSize() const {
*this->source_context_);
}
+ // optional .google.protobuf.Syntax syntax = 5;
+ if (this->syntax() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::EnumSize(this->syntax());
+ }
+
// repeated .google.protobuf.EnumValue enumvalue = 2;
total_size += 1 * this->enumvalue_size();
for (int i = 0; i < this->enumvalue_size(); i++) {
@@ -1959,6 +2174,9 @@ void Enum::MergeFrom(const Enum& from) {
if (from.has_source_context()) {
mutable_source_context()->::google::protobuf::SourceContext::MergeFrom(from.source_context());
}
+ if (from.syntax() != 0) {
+ set_syntax(from.syntax());
+ }
}
void Enum::CopyFrom(const ::google::protobuf::Message& from) {
@@ -1987,6 +2205,7 @@ void Enum::InternalSwap(Enum* other) {
enumvalue_.UnsafeArenaSwap(&other->enumvalue_);
options_.UnsafeArenaSwap(&other->options_);
std::swap(source_context_, other->source_context_);
+ std::swap(syntax_, other->syntax_);
_internal_metadata_.Swap(&other->_internal_metadata_);
std::swap(_cached_size_, other->_cached_size_);
}
@@ -2052,28 +2271,28 @@ int Enum::enumvalue_size() const {
void Enum::clear_enumvalue() {
enumvalue_.Clear();
}
- const ::google::protobuf::EnumValue& Enum::enumvalue(int index) const {
+const ::google::protobuf::EnumValue& Enum::enumvalue(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.Enum.enumvalue)
return enumvalue_.Get(index);
}
- ::google::protobuf::EnumValue* Enum::mutable_enumvalue(int index) {
+::google::protobuf::EnumValue* Enum::mutable_enumvalue(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.Enum.enumvalue)
return enumvalue_.Mutable(index);
}
- ::google::protobuf::EnumValue* Enum::add_enumvalue() {
+::google::protobuf::EnumValue* Enum::add_enumvalue() {
// @@protoc_insertion_point(field_add:google.protobuf.Enum.enumvalue)
return enumvalue_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >&
-Enum::enumvalue() const {
- // @@protoc_insertion_point(field_list:google.protobuf.Enum.enumvalue)
- return enumvalue_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >*
Enum::mutable_enumvalue() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.Enum.enumvalue)
return &enumvalue_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >&
+Enum::enumvalue() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Enum.enumvalue)
+ return enumvalue_;
+}
// repeated .google.protobuf.Option options = 3;
int Enum::options_size() const {
@@ -2082,28 +2301,28 @@ int Enum::options_size() const {
void Enum::clear_options() {
options_.Clear();
}
- const ::google::protobuf::Option& Enum::options(int index) const {
+const ::google::protobuf::Option& Enum::options(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.Enum.options)
return options_.Get(index);
}
- ::google::protobuf::Option* Enum::mutable_options(int index) {
+::google::protobuf::Option* Enum::mutable_options(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.Enum.options)
return options_.Mutable(index);
}
- ::google::protobuf::Option* Enum::add_options() {
+::google::protobuf::Option* Enum::add_options() {
// @@protoc_insertion_point(field_add:google.protobuf.Enum.options)
return options_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
-Enum::options() const {
- // @@protoc_insertion_point(field_list:google.protobuf.Enum.options)
- return options_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
Enum::mutable_options() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.Enum.options)
return &options_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Enum::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Enum.options)
+ return options_;
+}
// optional .google.protobuf.SourceContext source_context = 4;
bool Enum::has_source_context() const {
@@ -2113,11 +2332,11 @@ void Enum::clear_source_context() {
if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
}
- const ::google::protobuf::SourceContext& Enum::source_context() const {
+const ::google::protobuf::SourceContext& Enum::source_context() const {
// @@protoc_insertion_point(field_get:google.protobuf.Enum.source_context)
return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
}
- ::google::protobuf::SourceContext* Enum::mutable_source_context() {
+::google::protobuf::SourceContext* Enum::mutable_source_context() {
if (source_context_ == NULL) {
source_context_ = new ::google::protobuf::SourceContext;
@@ -2125,13 +2344,13 @@ void Enum::clear_source_context() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Enum.source_context)
return source_context_;
}
- ::google::protobuf::SourceContext* Enum::release_source_context() {
+::google::protobuf::SourceContext* Enum::release_source_context() {
::google::protobuf::SourceContext* temp = source_context_;
source_context_ = NULL;
return temp;
}
- void Enum::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
+void Enum::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
delete source_context_;
source_context_ = source_context;
if (source_context) {
@@ -2142,6 +2361,20 @@ void Enum::clear_source_context() {
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Enum.source_context)
}
+// optional .google.protobuf.Syntax syntax = 5;
+void Enum::clear_syntax() {
+ syntax_ = 0;
+}
+ ::google::protobuf::Syntax Enum::syntax() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Enum.syntax)
+ return static_cast< ::google::protobuf::Syntax >(syntax_);
+}
+ void Enum::set_syntax(::google::protobuf::Syntax value) {
+
+ syntax_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Enum.syntax)
+}
+
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -2235,10 +2468,10 @@ bool EnumValue::MergePartialFromCodedStream(
if (tag == 10) {
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_name()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.EnumValue.name");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.EnumValue.name"));
} else {
goto handle_unusual;
}
@@ -2304,9 +2537,9 @@ void EnumValue::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_start:google.protobuf.EnumValue)
// optional string name = 1;
if (this->name().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.EnumValue.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
@@ -2331,9 +2564,9 @@ void EnumValue::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValue)
// optional string name = 1;
if (this->name().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.EnumValue.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
@@ -2515,28 +2748,28 @@ int EnumValue::options_size() const {
void EnumValue::clear_options() {
options_.Clear();
}
- const ::google::protobuf::Option& EnumValue::options(int index) const {
+const ::google::protobuf::Option& EnumValue::options(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.EnumValue.options)
return options_.Get(index);
}
- ::google::protobuf::Option* EnumValue::mutable_options(int index) {
+::google::protobuf::Option* EnumValue::mutable_options(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.EnumValue.options)
return options_.Mutable(index);
}
- ::google::protobuf::Option* EnumValue::add_options() {
+::google::protobuf::Option* EnumValue::add_options() {
// @@protoc_insertion_point(field_add:google.protobuf.EnumValue.options)
return options_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
-EnumValue::options() const {
- // @@protoc_insertion_point(field_list:google.protobuf.EnumValue.options)
- return options_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
EnumValue::mutable_options() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValue.options)
return &options_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+EnumValue::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumValue.options)
+ return options_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -2632,10 +2865,10 @@ bool Option::MergePartialFromCodedStream(
if (tag == 10) {
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_name()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.Option.name");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.Option.name"));
} else {
goto handle_unusual;
}
@@ -2682,9 +2915,9 @@ void Option::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_start:google.protobuf.Option)
// optional string name = 1;
if (this->name().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Option.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
@@ -2704,9 +2937,9 @@ void Option::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Option)
// optional string name = 1;
if (this->name().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Option.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
@@ -2860,11 +3093,11 @@ void Option::clear_value() {
if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_;
value_ = NULL;
}
- const ::google::protobuf::Any& Option::value() const {
+const ::google::protobuf::Any& Option::value() const {
// @@protoc_insertion_point(field_get:google.protobuf.Option.value)
return value_ != NULL ? *value_ : *default_instance_->value_;
}
- ::google::protobuf::Any* Option::mutable_value() {
+::google::protobuf::Any* Option::mutable_value() {
if (value_ == NULL) {
value_ = new ::google::protobuf::Any;
@@ -2872,13 +3105,13 @@ void Option::clear_value() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Option.value)
return value_;
}
- ::google::protobuf::Any* Option::release_value() {
+::google::protobuf::Any* Option::release_value() {
::google::protobuf::Any* temp = value_;
value_ = NULL;
return temp;
}
- void Option::set_allocated_value(::google::protobuf::Any* value) {
+void Option::set_allocated_value(::google::protobuf::Any* value) {
delete value_;
value_ = value;
if (value) {
diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h
index c9952efa..deda9213 100644
--- a/src/google/protobuf/type.pb.h
+++ b/src/google/protobuf/type.pb.h
@@ -40,11 +40,11 @@ void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto();
void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto();
-class Type;
-class Field;
class Enum;
class EnumValue;
+class Field;
class Option;
+class Type;
enum Field_Kind {
Field_Kind_TYPE_UNKNOWN = 0,
@@ -57,6 +57,7 @@ enum Field_Kind {
Field_Kind_TYPE_FIXED32 = 7,
Field_Kind_TYPE_BOOL = 8,
Field_Kind_TYPE_STRING = 9,
+ Field_Kind_TYPE_GROUP = 10,
Field_Kind_TYPE_MESSAGE = 11,
Field_Kind_TYPE_BYTES = 12,
Field_Kind_TYPE_UINT32 = 13,
@@ -106,6 +107,27 @@ inline bool Field_Cardinality_Parse(
return ::google::protobuf::internal::ParseNamedEnum<Field_Cardinality>(
Field_Cardinality_descriptor(), name, value);
}
+enum Syntax {
+ SYNTAX_PROTO2 = 0,
+ SYNTAX_PROTO3 = 1,
+ Syntax_INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,
+ Syntax_INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max
+};
+LIBPROTOBUF_EXPORT bool Syntax_IsValid(int value);
+const Syntax Syntax_MIN = SYNTAX_PROTO2;
+const Syntax Syntax_MAX = SYNTAX_PROTO3;
+const int Syntax_ARRAYSIZE = Syntax_MAX + 1;
+
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* Syntax_descriptor();
+inline const ::std::string& Syntax_Name(Syntax value) {
+ return ::google::protobuf::internal::NameOfEnum(
+ Syntax_descriptor(), value);
+}
+inline bool Syntax_Parse(
+ const ::std::string& name, Syntax* value) {
+ return ::google::protobuf::internal::ParseNamedEnum<Syntax>(
+ Syntax_descriptor(), name, value);
+}
// ===================================================================
class LIBPROTOBUF_EXPORT Type : public ::google::protobuf::Message {
@@ -182,10 +204,10 @@ class LIBPROTOBUF_EXPORT Type : public ::google::protobuf::Message {
const ::google::protobuf::Field& fields(int index) const;
::google::protobuf::Field* mutable_fields(int index);
::google::protobuf::Field* add_fields();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >&
- fields() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >*
mutable_fields();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >&
+ fields() const;
// repeated string oneofs = 3;
int oneofs_size() const;
@@ -210,10 +232,10 @@ class LIBPROTOBUF_EXPORT Type : public ::google::protobuf::Message {
const ::google::protobuf::Option& options(int index) const;
::google::protobuf::Option* mutable_options(int index);
::google::protobuf::Option* add_options();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
- options() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
mutable_options();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+ options() const;
// optional .google.protobuf.SourceContext source_context = 5;
bool has_source_context() const;
@@ -224,6 +246,12 @@ class LIBPROTOBUF_EXPORT Type : public ::google::protobuf::Message {
::google::protobuf::SourceContext* release_source_context();
void set_allocated_source_context(::google::protobuf::SourceContext* source_context);
+ // optional .google.protobuf.Syntax syntax = 6;
+ void clear_syntax();
+ static const int kSyntaxFieldNumber = 6;
+ ::google::protobuf::Syntax syntax() const;
+ void set_syntax(::google::protobuf::Syntax value);
+
// @@protoc_insertion_point(class_scope:google.protobuf.Type)
private:
@@ -234,6 +262,7 @@ class LIBPROTOBUF_EXPORT Type : public ::google::protobuf::Message {
::google::protobuf::RepeatedPtrField< ::std::string> oneofs_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
::google::protobuf::SourceContext* source_context_;
+ int syntax_;
mutable int _cached_size_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto();
@@ -309,6 +338,7 @@ class LIBPROTOBUF_EXPORT Field : public ::google::protobuf::Message {
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;
@@ -425,10 +455,21 @@ class LIBPROTOBUF_EXPORT Field : public ::google::protobuf::Message {
const ::google::protobuf::Option& options(int index) const;
::google::protobuf::Option* mutable_options(int index);
::google::protobuf::Option* add_options();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
- options() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
mutable_options();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+ options() const;
+
+ // optional string json_name = 10;
+ void clear_json_name();
+ static const int kJsonNameFieldNumber = 10;
+ const ::std::string& json_name() const;
+ void set_json_name(const ::std::string& value);
+ void set_json_name(const char* value);
+ void set_json_name(const char* value, size_t size);
+ ::std::string* mutable_json_name();
+ ::std::string* release_json_name();
+ void set_allocated_json_name(::std::string* json_name);
// @@protoc_insertion_point(class_scope:google.protobuf.Field)
private:
@@ -442,6 +483,7 @@ class LIBPROTOBUF_EXPORT Field : public ::google::protobuf::Message {
::google::protobuf::int32 oneof_index_;
::google::protobuf::internal::ArenaStringPtr type_url_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
+ ::google::protobuf::internal::ArenaStringPtr json_name_;
bool packed_;
mutable int _cached_size_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
@@ -527,10 +569,10 @@ class LIBPROTOBUF_EXPORT Enum : public ::google::protobuf::Message {
const ::google::protobuf::EnumValue& enumvalue(int index) const;
::google::protobuf::EnumValue* mutable_enumvalue(int index);
::google::protobuf::EnumValue* add_enumvalue();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >&
- enumvalue() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >*
mutable_enumvalue();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >&
+ enumvalue() const;
// repeated .google.protobuf.Option options = 3;
int options_size() const;
@@ -539,10 +581,10 @@ class LIBPROTOBUF_EXPORT Enum : public ::google::protobuf::Message {
const ::google::protobuf::Option& options(int index) const;
::google::protobuf::Option* mutable_options(int index);
::google::protobuf::Option* add_options();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
- options() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
mutable_options();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+ options() const;
// optional .google.protobuf.SourceContext source_context = 4;
bool has_source_context() const;
@@ -553,6 +595,12 @@ class LIBPROTOBUF_EXPORT Enum : public ::google::protobuf::Message {
::google::protobuf::SourceContext* release_source_context();
void set_allocated_source_context(::google::protobuf::SourceContext* source_context);
+ // optional .google.protobuf.Syntax syntax = 5;
+ void clear_syntax();
+ static const int kSyntaxFieldNumber = 5;
+ ::google::protobuf::Syntax syntax() const;
+ void set_syntax(::google::protobuf::Syntax value);
+
// @@protoc_insertion_point(class_scope:google.protobuf.Enum)
private:
@@ -562,6 +610,7 @@ class LIBPROTOBUF_EXPORT Enum : public ::google::protobuf::Message {
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue > enumvalue_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
::google::protobuf::SourceContext* source_context_;
+ int syntax_;
mutable int _cached_size_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto();
@@ -652,10 +701,10 @@ class LIBPROTOBUF_EXPORT EnumValue : public ::google::protobuf::Message {
const ::google::protobuf::Option& options(int index) const;
::google::protobuf::Option* mutable_options(int index);
::google::protobuf::Option* add_options();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
- options() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
mutable_options();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+ options() const;
// @@protoc_insertion_point(class_scope:google.protobuf.EnumValue)
private:
@@ -836,16 +885,16 @@ inline ::google::protobuf::Field* Type::add_fields() {
// @@protoc_insertion_point(field_add:google.protobuf.Type.fields)
return fields_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >&
-Type::fields() const {
- // @@protoc_insertion_point(field_list:google.protobuf.Type.fields)
- return fields_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >*
Type::mutable_fields() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.fields)
return &fields_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >&
+Type::fields() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Type.fields)
+ return fields_;
+}
// repeated string oneofs = 3;
inline int Type::oneofs_size() const {
@@ -920,16 +969,16 @@ inline ::google::protobuf::Option* Type::add_options() {
// @@protoc_insertion_point(field_add:google.protobuf.Type.options)
return options_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
-Type::options() const {
- // @@protoc_insertion_point(field_list:google.protobuf.Type.options)
- return options_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
Type::mutable_options() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.options)
return &options_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Type::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Type.options)
+ return options_;
+}
// optional .google.protobuf.SourceContext source_context = 5;
inline bool Type::has_source_context() const {
@@ -968,6 +1017,20 @@ inline void Type::set_allocated_source_context(::google::protobuf::SourceContext
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Type.source_context)
}
+// optional .google.protobuf.Syntax syntax = 6;
+inline void Type::clear_syntax() {
+ syntax_ = 0;
+}
+inline ::google::protobuf::Syntax Type::syntax() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Type.syntax)
+ return static_cast< ::google::protobuf::Syntax >(syntax_);
+}
+inline void Type::set_syntax(::google::protobuf::Syntax value) {
+
+ syntax_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Type.syntax)
+}
+
// -------------------------------------------------------------------
// Field
@@ -1147,15 +1210,58 @@ inline ::google::protobuf::Option* Field::add_options() {
// @@protoc_insertion_point(field_add:google.protobuf.Field.options)
return options_.Add();
}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Field::mutable_options() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Field.options)
+ return &options_;
+}
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
Field::options() const {
// @@protoc_insertion_point(field_list:google.protobuf.Field.options)
return options_;
}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
-Field::mutable_options() {
- // @@protoc_insertion_point(field_mutable_list:google.protobuf.Field.options)
- return &options_;
+
+// optional string json_name = 10;
+inline void Field::clear_json_name() {
+ json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Field::json_name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.json_name)
+ return json_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Field::set_json_name(const ::std::string& value) {
+
+ json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Field.json_name)
+}
+inline void Field::set_json_name(const char* value) {
+
+ json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Field.json_name)
+}
+inline void Field::set_json_name(const char* value, size_t size) {
+
+ json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.json_name)
+}
+inline ::std::string* Field::mutable_json_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Field.json_name)
+ return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Field::release_json_name() {
+
+ return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Field::set_allocated_json_name(::std::string* json_name) {
+ if (json_name != NULL) {
+
+ } else {
+
+ }
+ json_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), json_name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.json_name)
}
// -------------------------------------------------------------------
@@ -1224,16 +1330,16 @@ inline ::google::protobuf::EnumValue* Enum::add_enumvalue() {
// @@protoc_insertion_point(field_add:google.protobuf.Enum.enumvalue)
return enumvalue_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >&
-Enum::enumvalue() const {
- // @@protoc_insertion_point(field_list:google.protobuf.Enum.enumvalue)
- return enumvalue_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >*
Enum::mutable_enumvalue() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.Enum.enumvalue)
return &enumvalue_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >&
+Enum::enumvalue() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Enum.enumvalue)
+ return enumvalue_;
+}
// repeated .google.protobuf.Option options = 3;
inline int Enum::options_size() const {
@@ -1254,16 +1360,16 @@ inline ::google::protobuf::Option* Enum::add_options() {
// @@protoc_insertion_point(field_add:google.protobuf.Enum.options)
return options_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
-Enum::options() const {
- // @@protoc_insertion_point(field_list:google.protobuf.Enum.options)
- return options_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
Enum::mutable_options() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.Enum.options)
return &options_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Enum::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Enum.options)
+ return options_;
+}
// optional .google.protobuf.SourceContext source_context = 4;
inline bool Enum::has_source_context() const {
@@ -1302,6 +1408,20 @@ inline void Enum::set_allocated_source_context(::google::protobuf::SourceContext
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Enum.source_context)
}
+// optional .google.protobuf.Syntax syntax = 5;
+inline void Enum::clear_syntax() {
+ syntax_ = 0;
+}
+inline ::google::protobuf::Syntax Enum::syntax() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Enum.syntax)
+ return static_cast< ::google::protobuf::Syntax >(syntax_);
+}
+inline void Enum::set_syntax(::google::protobuf::Syntax value) {
+
+ syntax_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Enum.syntax)
+}
+
// -------------------------------------------------------------------
// EnumValue
@@ -1382,16 +1502,16 @@ inline ::google::protobuf::Option* EnumValue::add_options() {
// @@protoc_insertion_point(field_add:google.protobuf.EnumValue.options)
return options_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
-EnumValue::options() const {
- // @@protoc_insertion_point(field_list:google.protobuf.EnumValue.options)
- return options_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
EnumValue::mutable_options() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValue.options)
return &options_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+EnumValue::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumValue.options)
+ return options_;
+}
// -------------------------------------------------------------------
@@ -1506,6 +1626,11 @@ template <>
inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::Field_Cardinality>() {
return ::google::protobuf::Field_Cardinality_descriptor();
}
+template <> struct is_proto_enum< ::google::protobuf::Syntax> : ::google::protobuf::internal::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::Syntax>() {
+ return ::google::protobuf::Syntax_descriptor();
+}
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/type.proto b/src/google/protobuf/type.proto
index ce22d33d..4df95762 100644
--- a/src/google/protobuf/type.proto
+++ b/src/google/protobuf/type.proto
@@ -34,30 +34,27 @@ package google.protobuf;
import "google/protobuf/any.proto";
import "google/protobuf/source_context.proto";
-option java_multiple_files = true;
-option java_outer_classname = "TypeProto";
option java_package = "com.google.protobuf";
+option java_outer_classname = "TypeProto";
+option java_multiple_files = true;
+option java_generate_equals_and_hash = true;
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
option objc_class_prefix = "GPB";
-
// A light-weight descriptor for a proto message type.
message Type {
// The fully qualified message name.
string name = 1;
-
// The list of fields.
repeated Field fields = 2;
-
// The list of oneof definitions.
- // The list of oneofs declared in this Type
- repeated string oneofs = 3;
-
+ repeated string oneofs = 3; // The list of oneofs declared in this Type
// The proto options.
repeated Option options = 4;
-
// The source context.
SourceContext source_context = 5;
+ // The source syntax.
+ Syntax syntax = 6;
}
// Field represents a single field of a message type.
@@ -65,125 +62,99 @@ message Field {
// Kind represents a basic field type.
enum Kind {
// Field type unknown.
- TYPE_UNKNOWN = 0;
-
+ TYPE_UNKNOWN = 0;
// Field type double.
- TYPE_DOUBLE = 1;
-
+ TYPE_DOUBLE = 1;
// Field type float.
- TYPE_FLOAT = 2;
-
+ TYPE_FLOAT = 2;
// Field type int64.
- TYPE_INT64 = 3;
-
+ TYPE_INT64 = 3;
// Field type uint64.
- TYPE_UINT64 = 4;
-
+ TYPE_UINT64 = 4;
// Field type int32.
- TYPE_INT32 = 5;
-
+ TYPE_INT32 = 5;
// Field type fixed64.
- TYPE_FIXED64 = 6;
-
+ TYPE_FIXED64 = 6;
// Field type fixed32.
- TYPE_FIXED32 = 7;
-
+ TYPE_FIXED32 = 7;
// Field type bool.
- TYPE_BOOL = 8;
-
+ TYPE_BOOL = 8;
// Field type string.
- TYPE_STRING = 9;
-
+ TYPE_STRING = 9;
+ // Field type group (deprecated proto2 type)
+ TYPE_GROUP = 10;
// Field type message.
- TYPE_MESSAGE = 11;
-
+ TYPE_MESSAGE = 11;
// Field type bytes.
- TYPE_BYTES = 12;
-
+ TYPE_BYTES = 12;
// Field type uint32.
- TYPE_UINT32 = 13;
-
+ TYPE_UINT32 = 13;
// Field type enum.
- TYPE_ENUM = 14;
-
+ TYPE_ENUM = 14;
// Field type sfixed32.
- TYPE_SFIXED32 = 15;
-
+ TYPE_SFIXED32 = 15;
// Field type sfixed64.
- TYPE_SFIXED64 = 16;
-
+ TYPE_SFIXED64 = 16;
// Field type sint32.
- TYPE_SINT32 = 17;
-
+ TYPE_SINT32 = 17;
// Field type sint64.
- TYPE_SINT64 = 18;
- }
+ TYPE_SINT64 = 18;
+ };
// Cardinality represents whether a field is optional, required, or
// repeated.
enum Cardinality {
// The field cardinality is unknown. Typically an error condition.
CARDINALITY_UNKNOWN = 0;
-
// For optional fields.
CARDINALITY_OPTIONAL = 1;
-
// For required fields. Not used for proto3.
CARDINALITY_REQUIRED = 2;
-
// For repeated fields.
CARDINALITY_REPEATED = 3;
- }
+ };
// The field kind.
Kind kind = 1;
-
// The field cardinality, i.e. optional/required/repeated.
Cardinality cardinality = 2;
-
// The proto field number.
int32 number = 3;
-
// The field name.
string name = 4;
-
// The type URL (without the scheme) when the type is MESSAGE or ENUM,
// such as `type.googleapis.com/google.protobuf.Empty`.
string type_url = 6;
-
// Index in Type.oneofs. Starts at 1. Zero means no oneof mapping.
int32 oneof_index = 7;
-
// Whether to use alternative packed wire representation.
bool packed = 8;
-
// The proto options.
repeated Option options = 9;
+ // The JSON name for this field.
+ string json_name = 10;
}
// Enum type definition.
message Enum {
// Enum type name.
string name = 1;
-
// Enum value definitions.
repeated EnumValue enumvalue = 2;
-
// Proto options for the enum type.
repeated Option options = 3;
-
// The source context.
SourceContext source_context = 4;
+ // The source syntax.
+ Syntax syntax = 5;
}
// Enum value definition.
message EnumValue {
// Enum value name.
string name = 1;
-
// Enum value number.
int32 number = 2;
-
// Proto options for the enum value.
repeated Option options = 3;
}
@@ -192,7 +163,14 @@ message EnumValue {
message Option {
// Proto option name.
string name = 1;
-
// Proto option value.
Any value = 2;
}
+
+// Syntax specifies the syntax in which a service element was defined.
+enum Syntax {
+ // Syntax "proto2"
+ SYNTAX_PROTO2 = 0;
+ // Syntax "proto3"
+ SYNTAX_PROTO3 = 1;
+}
diff --git a/src/google/protobuf/unittest_mset.proto b/src/google/protobuf/unittest_mset.proto
index 3aa31fa9..49d9adad 100644
--- a/src/google/protobuf/unittest_mset.proto
+++ b/src/google/protobuf/unittest_mset.proto
@@ -32,33 +32,31 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
-// This file contains messages for testing message_set_wire_format.
+// This file is similar to unittest_mset_wire_format.proto, but does not
+// have a TestMessageSet, so it can be downgraded to proto1.
syntax = "proto2";
+
+import "google/protobuf/unittest_mset_wire_format.proto";
+
package protobuf_unittest;
option cc_enable_arenas = true;
option optimize_for = SPEED;
-// A message with message_set_wire_format.
-message TestMessageSet {
- option message_set_wire_format = true;
- extensions 4 to max;
-}
-
message TestMessageSetContainer {
- optional TestMessageSet message_set = 1;
+ optional proto2_wireformat_unittest.TestMessageSet message_set = 1;
}
message TestMessageSetExtension1 {
- extend TestMessageSet {
+ extend proto2_wireformat_unittest.TestMessageSet {
optional TestMessageSetExtension1 message_set_extension = 1545008;
}
optional int32 i = 15;
}
message TestMessageSetExtension2 {
- extend TestMessageSet {
+ extend proto2_wireformat_unittest.TestMessageSet {
optional TestMessageSetExtension2 message_set_extension = 1547769;
}
optional string str = 25;
@@ -82,4 +80,3 @@ message RawMessageSet {
required bytes message = 3;
}
}
-
diff --git a/src/google/protobuf/unittest_mset_wire_format.proto b/src/google/protobuf/unittest_mset_wire_format.proto
new file mode 100644
index 00000000..04e4352e
--- /dev/null
+++ b/src/google/protobuf/unittest_mset_wire_format.proto
@@ -0,0 +1,52 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file contains messages for testing message_set_wire_format.
+
+syntax = "proto2";
+package proto2_wireformat_unittest;
+
+option cc_enable_arenas = true;
+option optimize_for = SPEED;
+option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
+
+// A message with message_set_wire_format.
+message TestMessageSet {
+ option message_set_wire_format = true;
+ extensions 4 to max;
+}
+
+message TestMessageSetWireFormatContainer {
+ optional TestMessageSet message_set = 1;
+}
diff --git a/src/google/protobuf/unittest_no_arena.proto b/src/google/protobuf/unittest_no_arena.proto
index 36fb8656..41518df2 100644
--- a/src/google/protobuf/unittest_no_arena.proto
+++ b/src/google/protobuf/unittest_no_arena.proto
@@ -44,6 +44,7 @@ option cc_generic_services = true; // auto-added
option java_generic_services = true; // auto-added
option py_generic_services = true; // auto-added
option cc_enable_arenas = false;
+option objc_class_prefix = "NOARN";
import "google/protobuf/unittest_import.proto";
import "google/protobuf/unittest_arena.proto";
diff --git a/src/google/protobuf/unittest_no_arena_lite.proto b/src/google/protobuf/unittest_no_arena_lite.proto
new file mode 100644
index 00000000..34c7b7ce
--- /dev/null
+++ b/src/google/protobuf/unittest_no_arena_lite.proto
@@ -0,0 +1,42 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In test_util.h we do "using namespace unittest = protobuf_unittest".
+package protobuf_unittest_no_arena;
+
+message ForeignMessageLite {
+ optional int32 c = 1;
+}
diff --git a/src/google/protobuf/unknown_enum_impl.h b/src/google/protobuf/unknown_enum_impl.h
index 39c10cbc..7c68ad6c 100644
--- a/src/google/protobuf/unknown_enum_impl.h
+++ b/src/google/protobuf/unknown_enum_impl.h
@@ -34,7 +34,6 @@
#include <stdlib.h>
#include <google/protobuf/stubs/common.h>
-#include "net/proto/tagmapper.h"
#include <google/protobuf/bridge/compatibility_mode_support.h>
namespace google {
@@ -59,10 +58,10 @@ namespace util {
// In proto2, invalid enum values will be treated as unknown fields. This
// function checks that case.
bool HasUnknownEnum(const Message& message, int32 field_number,
- int32* unknown_value = nullptr);
+ int32* unknown_value = NULL);
// Same as above, but returns all unknown enums.
bool GetRepeatedEnumUnknowns(const Message& message, int32 field_number,
- vector<int32>* unknown_values = nullptr);
+ vector<int32>* unknown_values = NULL);
// In proto1, invalue enum values are stored in the same way as valid enum
// values.
// TODO(karner): Delete this once the migration to proto2 is complete.
@@ -75,7 +74,7 @@ bool GetRepeatedEnumUnknownsProto1(const Message& message, int32 field_number,
// or proto2.
template <typename T>
bool HasUnknownEnum_Template(const T& message, int32 field_number,
- int32* unknown_value = nullptr) {
+ int32* unknown_value = NULL) {
if (internal::is_base_of<bridge::internal::Proto1CompatibleMessage, T>::value ||
!internal::is_base_of<ProtocolMessage, T>::value) {
return HasUnknownEnum(message, field_number, unknown_value);
@@ -88,7 +87,7 @@ bool HasUnknownEnum_Template(const T& message, int32 field_number,
template <typename T>
bool GetRepeatedEnumUnknowns_Template(
const T& message, int32 field_number,
- vector<int32>* unknown_values = nullptr) {
+ vector<int32>* unknown_values = NULL) {
if (internal::is_base_of<bridge::internal::Proto1CompatibleMessage, T>::value ||
!internal::is_base_of<ProtocolMessage, T>::value) {
return GetRepeatedEnumUnknowns(message, field_number, unknown_values);
diff --git a/src/google/protobuf/unknown_enum_test.proto b/src/google/protobuf/unknown_enum_test.proto
index 0ea1ede3..3c549cc7 100644
--- a/src/google/protobuf/unknown_enum_test.proto
+++ b/src/google/protobuf/unknown_enum_test.proto
@@ -36,6 +36,8 @@ syntax = "proto2";
package google.protobuf.util;
+option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
+
message DownRevision {
enum Enum {
DEFAULT_VALUE = 2;
diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
index 93f0f206..d4e383da 100644
--- a/src/google/protobuf/unknown_field_set.cc
+++ b/src/google/protobuf/unknown_field_set.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream.h>
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index 6781cd0f..612a942a 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -42,6 +42,7 @@
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/unknown_field_set_unittest.cc b/src/google/protobuf/unknown_field_set_unittest.cc
index 9b02f0b0..5de72630 100644
--- a/src/google/protobuf/unknown_field_set_unittest.cc
+++ b/src/google/protobuf/unknown_field_set_unittest.cc
@@ -43,7 +43,10 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/test_util.h>
+#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/mutex.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
#include <google/protobuf/stubs/stl_util.h>
diff --git a/src/google/protobuf/util/field_comparator_test.cc b/src/google/protobuf/util/field_comparator_test.cc
index 748c7d11..845839ac 100644
--- a/src/google/protobuf/util/field_comparator_test.cc
+++ b/src/google/protobuf/util/field_comparator_test.cc
@@ -34,8 +34,8 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/descriptor.h>
-#include <gtest/gtest.h>
#include <google/protobuf/stubs/mathutil.h>
+#include <gtest/gtest.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/util/field_mask_util.cc b/src/google/protobuf/util/field_mask_util.cc
new file mode 100644
index 00000000..82034bd4
--- /dev/null
+++ b/src/google/protobuf/util/field_mask_util.cc
@@ -0,0 +1,418 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/field_mask_util.h>
+
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/map_util.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+using google::protobuf::FieldMask;
+
+string FieldMaskUtil::ToString(const FieldMask& mask) {
+ return Join(mask.paths(), ",");
+}
+
+void FieldMaskUtil::FromString(const string& str, FieldMask* out) {
+ out->Clear();
+ vector<string> paths = Split(str, ",");
+ for (int i = 0; i < paths.size(); ++i) {
+ if (paths[i].empty()) continue;
+ out->add_paths(paths[i]);
+ }
+}
+
+bool FieldMaskUtil::InternalIsValidPath(const Descriptor* descriptor,
+ const string& path) {
+ vector<string> parts = Split(path, ".");
+ for (int i = 0; i < parts.size(); ++i) {
+ const string& field_name = parts[i];
+ if (descriptor == NULL) {
+ return false;
+ }
+ const FieldDescriptor* field = descriptor->FindFieldByName(field_name);
+ if (field == NULL) {
+ return false;
+ }
+ if (!field->is_repeated() &&
+ field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ descriptor = field->message_type();
+ } else {
+ descriptor = NULL;
+ }
+ }
+ return true;
+}
+
+void FieldMaskUtil::InternalGetFieldMaskForAllFields(
+ const Descriptor* descriptor, FieldMask* out) {
+ for (int i = 0; i < descriptor->field_count(); ++i) {
+ out->add_paths(descriptor->field(i)->name());
+ }
+}
+
+namespace {
+// A FieldMaskTree represents a FieldMask in a tree structure. For example,
+// given a FieldMask "foo.bar,foo.baz,bar.baz", the FieldMaskTree will be:
+//
+// [root] -+- foo -+- bar
+// | |
+// | +- baz
+// |
+// +- bar --- baz
+//
+// In the tree, each leaf node represents a field path.
+class FieldMaskTree {
+ public:
+ FieldMaskTree();
+ ~FieldMaskTree();
+
+ void MergeFromFieldMask(const FieldMask& mask);
+ void MergeToFieldMask(FieldMask* mask);
+
+ // Add a field path into the tree. In a FieldMask, each field path matches
+ // the specified field and also all its sub-fields. If the field path to
+ // add is a sub-path of an existing field path in the tree (i.e., a leaf
+ // node), it means the tree already matchesthe the given path so nothing will
+ // be added to the tree. If the path matches an existing non-leaf node in the
+ // tree, that non-leaf node will be turned into a leaf node with all its
+ // children removed because the path matches all the node's children.
+ void AddPath(const string& path);
+
+ // Calculate the intersection part of a field path with this tree and add
+ // the intersection field path into out.
+ void IntersectPath(const string& path, FieldMaskTree* out);
+
+ // Merge all fields specified by this tree from one message to another.
+ void MergeMessage(const Message& source,
+ const FieldMaskUtil::MergeOptions& options,
+ Message* destination) {
+ // Do nothing if the tree is empty.
+ if (root_.children.empty()) {
+ return;
+ }
+ MergeMessage(&root_, source, options, destination);
+ }
+
+ private:
+ struct Node {
+ Node() {}
+
+ ~Node() { ClearChildren(); }
+
+ void ClearChildren() {
+ for (map<string, Node*>::iterator it = children.begin();
+ it != children.end(); ++it) {
+ delete it->second;
+ }
+ children.clear();
+ }
+
+ map<string, Node*> children;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node);
+ };
+
+ // Merge a sub-tree to mask. This method adds the field paths represented
+ // by all leaf nodes descended from "node" to mask.
+ void MergeToFieldMask(const string& prefix, const Node* node, FieldMask* out);
+
+ // Merge all leaf nodes of a sub-tree to another tree.
+ void MergeLeafNodesToTree(const string& prefix, const Node* node,
+ FieldMaskTree* out);
+
+ // Merge all fields specified by a sub-tree from one message to another.
+ void MergeMessage(const Node* node, const Message& source,
+ const FieldMaskUtil::MergeOptions& options,
+ Message* destination);
+
+ Node root_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldMaskTree);
+};
+
+FieldMaskTree::FieldMaskTree() {}
+
+FieldMaskTree::~FieldMaskTree() {}
+
+void FieldMaskTree::MergeFromFieldMask(const FieldMask& mask) {
+ for (int i = 0; i < mask.paths_size(); ++i) {
+ AddPath(mask.paths(i));
+ }
+}
+
+void FieldMaskTree::MergeToFieldMask(FieldMask* mask) {
+ MergeToFieldMask("", &root_, mask);
+}
+
+void FieldMaskTree::MergeToFieldMask(const string& prefix, const Node* node,
+ FieldMask* out) {
+ if (node->children.empty()) {
+ if (prefix.empty()) {
+ // This is the root node.
+ return;
+ }
+ out->add_paths(prefix);
+ return;
+ }
+ for (map<string, Node*>::const_iterator it = node->children.begin();
+ it != node->children.end(); ++it) {
+ string current_path = prefix.empty() ? it->first : prefix + "." + it->first;
+ MergeToFieldMask(current_path, it->second, out);
+ }
+}
+
+void FieldMaskTree::AddPath(const string& path) {
+ vector<string> parts = Split(path, ".");
+ if (parts.empty()) {
+ return;
+ }
+ bool new_branch = false;
+ Node* node = &root_;
+ for (int i = 0; i < parts.size(); ++i) {
+ if (!new_branch && node != &root_ && node->children.empty()) {
+ // Path matches an existing leaf node. This means the path is already
+ // coverred by this tree (for example, adding "foo.bar.baz" to a tree
+ // which already contains "foo.bar").
+ return;
+ }
+ const string& node_name = parts[i];
+ Node*& child = node->children[node_name];
+ if (child == NULL) {
+ new_branch = true;
+ child = new Node();
+ }
+ node = child;
+ }
+ if (!node->children.empty()) {
+ node->ClearChildren();
+ }
+}
+
+void FieldMaskTree::IntersectPath(const string& path, FieldMaskTree* out) {
+ vector<string> parts = Split(path, ".");
+ if (parts.empty()) {
+ return;
+ }
+ const Node* node = &root_;
+ for (int i = 0; i < parts.size(); ++i) {
+ if (node->children.empty()) {
+ if (node != &root_) {
+ out->AddPath(path);
+ }
+ return;
+ }
+ const string& node_name = parts[i];
+ const Node* result = FindPtrOrNull(node->children, node_name);
+ if (result == NULL) {
+ // No intersection found.
+ return;
+ }
+ node = result;
+ }
+ // Now we found a matching node with the given path. Add all leaf nodes
+ // to out.
+ MergeLeafNodesToTree(path, node, out);
+}
+
+void FieldMaskTree::MergeLeafNodesToTree(const string& prefix, const Node* node,
+ FieldMaskTree* out) {
+ if (node->children.empty()) {
+ out->AddPath(prefix);
+ }
+ for (map<string, Node*>::const_iterator it = node->children.begin();
+ it != node->children.end(); ++it) {
+ string current_path = prefix.empty() ? it->first : prefix + "." + it->first;
+ MergeLeafNodesToTree(current_path, it->second, out);
+ }
+}
+
+void FieldMaskTree::MergeMessage(const Node* node, const Message& source,
+ const FieldMaskUtil::MergeOptions& options,
+ Message* destination) {
+ GOOGLE_DCHECK(!node->children.empty());
+ const Reflection* source_reflection = source.GetReflection();
+ const Reflection* destination_reflection = destination->GetReflection();
+ const Descriptor* descriptor = source.GetDescriptor();
+ for (map<string, Node*>::const_iterator it = node->children.begin();
+ it != node->children.end(); ++it) {
+ const string& field_name = it->first;
+ const Node* child = it->second;
+ const FieldDescriptor* field = descriptor->FindFieldByName(field_name);
+ if (field == NULL) {
+ GOOGLE_LOG(ERROR) << "Cannot find field \"" << field_name << "\" in message "
+ << descriptor->full_name();
+ continue;
+ }
+ if (!child->children.empty()) {
+ // Sub-paths are only allowed for singular message fields.
+ if (field->is_repeated() ||
+ field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+ GOOGLE_LOG(ERROR) << "Field \"" << field_name << "\" in message "
+ << descriptor->full_name()
+ << " is not a singular message field and cannot "
+ << "have sub-fields.";
+ continue;
+ }
+ MergeMessage(child, source_reflection->GetMessage(source, field), options,
+ destination_reflection->MutableMessage(destination, field));
+ continue;
+ }
+ if (!field->is_repeated()) {
+ switch (field->cpp_type()) {
+#define COPY_VALUE(TYPE, Name) \
+ case FieldDescriptor::CPPTYPE_##TYPE: { \
+ destination_reflection->Set##Name( \
+ destination, field, source_reflection->Get##Name(source, field)); \
+ break; \
+ }
+ COPY_VALUE(BOOL, Bool)
+ COPY_VALUE(INT32, Int32)
+ COPY_VALUE(INT64, Int64)
+ COPY_VALUE(UINT32, UInt32)
+ COPY_VALUE(UINT64, UInt64)
+ COPY_VALUE(FLOAT, Float)
+ COPY_VALUE(DOUBLE, Double)
+ COPY_VALUE(ENUM, Enum)
+ COPY_VALUE(STRING, String)
+#undef COPY_VALUE
+ case FieldDescriptor::CPPTYPE_MESSAGE: {
+ if (options.replace_message_fields()) {
+ destination_reflection->ClearField(destination, field);
+ }
+ if (source_reflection->HasField(source, field)) {
+ destination_reflection->MutableMessage(destination, field)
+ ->MergeFrom(source_reflection->GetMessage(source, field));
+ }
+ break;
+ }
+ }
+ } else {
+ if (options.replace_repeated_fields()) {
+ destination_reflection->ClearField(destination, field);
+ }
+ switch (field->cpp_type()) {
+#define COPY_REPEATED_VALUE(TYPE, Name) \
+ case FieldDescriptor::CPPTYPE_##TYPE: { \
+ int size = source_reflection->FieldSize(source, field); \
+ for (int i = 0; i < size; ++i) { \
+ destination_reflection->Add##Name( \
+ destination, field, \
+ source_reflection->GetRepeated##Name(source, field, i)); \
+ } \
+ break; \
+ }
+ COPY_REPEATED_VALUE(BOOL, Bool)
+ COPY_REPEATED_VALUE(INT32, Int32)
+ COPY_REPEATED_VALUE(INT64, Int64)
+ COPY_REPEATED_VALUE(UINT32, UInt32)
+ COPY_REPEATED_VALUE(UINT64, UInt64)
+ COPY_REPEATED_VALUE(FLOAT, Float)
+ COPY_REPEATED_VALUE(DOUBLE, Double)
+ COPY_REPEATED_VALUE(ENUM, Enum)
+ COPY_REPEATED_VALUE(STRING, String)
+#undef COPY_REPEATED_VALUE
+ case FieldDescriptor::CPPTYPE_MESSAGE: {
+ int size = source_reflection->FieldSize(source, field);
+ for (int i = 0; i < size; ++i) {
+ destination_reflection->AddMessage(destination, field)
+ ->MergeFrom(
+ source_reflection->GetRepeatedMessage(source, field, i));
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+} // namespace
+
+void FieldMaskUtil::ToCanonicalForm(const FieldMask& mask, FieldMask* out) {
+ FieldMaskTree tree;
+ tree.MergeFromFieldMask(mask);
+ out->Clear();
+ tree.MergeToFieldMask(out);
+}
+
+void FieldMaskUtil::Union(const FieldMask& mask1, const FieldMask& mask2,
+ FieldMask* out) {
+ FieldMaskTree tree;
+ tree.MergeFromFieldMask(mask1);
+ tree.MergeFromFieldMask(mask2);
+ out->Clear();
+ tree.MergeToFieldMask(out);
+}
+
+void FieldMaskUtil::Intersect(const FieldMask& mask1, const FieldMask& mask2,
+ FieldMask* out) {
+ FieldMaskTree tree, intersection;
+ tree.MergeFromFieldMask(mask1);
+ for (int i = 0; i < mask2.paths_size(); ++i) {
+ tree.IntersectPath(mask2.paths(i), &intersection);
+ }
+ out->Clear();
+ intersection.MergeToFieldMask(out);
+}
+
+bool FieldMaskUtil::IsPathInFieldMask(const string& path,
+ const FieldMask& mask) {
+ for (int i = 0; i < mask.paths_size(); ++i) {
+ const string& mask_path = mask.paths(i);
+ if (path == mask_path) {
+ return true;
+ } else if (mask_path.length() < path.length()) {
+ // Also check whether mask.paths(i) is a prefix of path.
+ if (path.compare(0, mask_path.length() + 1, mask_path + ".") == 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void FieldMaskUtil::MergeMessageTo(const Message& source, const FieldMask& mask,
+ const MergeOptions& options,
+ Message* destination) {
+ GOOGLE_CHECK(source.GetDescriptor() == destination->GetDescriptor());
+ // Build a FieldMaskTree and walk through the tree to merge all specified
+ // fields.
+ FieldMaskTree tree;
+ tree.MergeFromFieldMask(mask);
+ tree.MergeMessage(source, options, destination);
+}
+
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/field_mask_util.h b/src/google/protobuf/util/field_mask_util.h
new file mode 100644
index 00000000..c99c34f8
--- /dev/null
+++ b/src/google/protobuf/util/field_mask_util.h
@@ -0,0 +1,146 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__
+#define GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__
+
+#include <string>
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/field_mask.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+class LIBPROTOBUF_EXPORT FieldMaskUtil {
+ typedef google::protobuf::FieldMask FieldMask;
+
+ public:
+ // Converts FieldMask to/from string, formatted according to proto3 JSON
+ // spec for FieldMask (e.g., "foo,bar,baz.quz").
+ static string ToString(const FieldMask& mask);
+ static void FromString(const string& str, FieldMask* out);
+
+ // Checks whether the given path is valid for type T.
+ template <typename T>
+ static bool IsValidPath(const string& path) {
+ return InternalIsValidPath(T::descriptor(), path);
+ }
+
+ // Checks whether the given FieldMask is valid for type T.
+ template <typename T>
+ static bool IsValidFieldMask(const FieldMask& mask) {
+ for (int i = 0; i < mask.paths_size(); ++i) {
+ if (!InternalIsValidPath(T::descriptor(), mask.paths(i))) return false;
+ }
+ return true;
+ }
+
+ // Adds a path to FieldMask after checking whether the given path is valid.
+ // This method check-fails if the path is not a valid path for type T.
+ template <typename T>
+ static void AddPathToFieldMask(const string& path, FieldMask* mask) {
+ GOOGLE_CHECK(IsValidPath<T>(path));
+ mask->add_paths(path);
+ }
+
+ // Creates a FieldMask with all fields of type T. This FieldMask only
+ // contains fields of T but not any sub-message fields.
+ template <typename T>
+ static void GetFieldMaskForAllFields(FieldMask* out) {
+ InternalGetFieldMaskForAllFields(T::descriptor(), out);
+ }
+
+ // Converts a FieldMask to the canonical form. It will:
+ // 1. Remove paths that are covered by another path. For example,
+ // "foo.bar" is covered by "foo" and will be removed if "foo"
+ // is also in the FieldMask.
+ // 2. Sort all paths in alphabetical order.
+ static void ToCanonicalForm(const FieldMask& mask, FieldMask* out);
+
+ // Creates an union of two FieldMasks.
+ static void Union(const FieldMask& mask1, const FieldMask& mask2,
+ FieldMask* out);
+
+ // Creates an intersection of two FieldMasks.
+ static void Intersect(const FieldMask& mask1, const FieldMask& mask2,
+ FieldMask* out);
+
+ // Returns true if path is covered by the given FieldMask. Note that path
+ // "foo.bar" covers all paths like "foo.bar.baz", "foo.bar.quz.x", etc.
+ static bool IsPathInFieldMask(const string& path, const FieldMask& mask);
+
+ class MergeOptions;
+ // Merges fields specified in a FieldMask into another message.
+ static void MergeMessageTo(const Message& source, const FieldMask& mask,
+ const MergeOptions& options, Message* destination);
+
+ private:
+ static bool InternalIsValidPath(const Descriptor* descriptor,
+ const string& path);
+
+ static void InternalGetFieldMaskForAllFields(const Descriptor* descriptor,
+ FieldMask* out);
+};
+
+class LIBPROTOBUF_EXPORT FieldMaskUtil::MergeOptions {
+ public:
+ MergeOptions()
+ : replace_message_fields_(false), replace_repeated_fields_(false) {}
+ // When merging message fields, the default behavior is to merge the
+ // content of two message fields together. If you instead want to use
+ // the field from the source message to replace the corresponding field
+ // in the destination message, set this flag to true. When this flag is set,
+ // specified submessage fields that are missing in source will be cleared in
+ // destination.
+ void set_replace_message_fields(bool value) {
+ replace_message_fields_ = value;
+ }
+ bool replace_message_fields() const { return replace_message_fields_; }
+ // The default merging behavior will append entries from the source
+ // repeated field to the destination repeated field. If you only want
+ // to keep the entries from the source repeated field, set this flag
+ // to true.
+ void set_replace_repeated_fields(bool value) {
+ replace_repeated_fields_ = value;
+ }
+ bool replace_repeated_fields() const { return replace_repeated_fields_; }
+
+ private:
+ bool replace_message_fields_;
+ bool replace_repeated_fields_;
+};
+
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__
diff --git a/src/google/protobuf/util/field_mask_util_test.cc b/src/google/protobuf/util/field_mask_util_test.cc
new file mode 100644
index 00000000..a9523250
--- /dev/null
+++ b/src/google/protobuf/util/field_mask_util_test.cc
@@ -0,0 +1,395 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/field_mask_util.h>
+
+#include <google/protobuf/field_mask.pb.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/test_util.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace {
+
+using protobuf_unittest::TestAllTypes;
+using protobuf_unittest::NestedTestAllTypes;
+using google::protobuf::FieldMask;
+
+TEST(FieldMaskUtilTest, StringFormat) {
+ FieldMask mask;
+ EXPECT_EQ("", FieldMaskUtil::ToString(mask));
+ mask.add_paths("foo");
+ EXPECT_EQ("foo", FieldMaskUtil::ToString(mask));
+ mask.add_paths("bar");
+ EXPECT_EQ("foo,bar", FieldMaskUtil::ToString(mask));
+
+ FieldMaskUtil::FromString("", &mask);
+ EXPECT_EQ(0, mask.paths_size());
+ FieldMaskUtil::FromString("foo", &mask);
+ EXPECT_EQ(1, mask.paths_size());
+ EXPECT_EQ("foo", mask.paths(0));
+ FieldMaskUtil::FromString("foo,bar", &mask);
+ EXPECT_EQ(2, mask.paths_size());
+ EXPECT_EQ("foo", mask.paths(0));
+ EXPECT_EQ("bar", mask.paths(1));
+}
+
+TEST(FieldMaskUtilTest, TestIsVaildPath) {
+ EXPECT_TRUE(FieldMaskUtil::IsValidPath<TestAllTypes>("optional_int32"));
+ EXPECT_FALSE(FieldMaskUtil::IsValidPath<TestAllTypes>("optional_nonexist"));
+ EXPECT_TRUE(
+ FieldMaskUtil::IsValidPath<TestAllTypes>("optional_nested_message.bb"));
+ EXPECT_FALSE(FieldMaskUtil::IsValidPath<TestAllTypes>(
+ "optional_nested_message.nonexist"));
+ // FieldMask cannot be used to specify sub-fields of a repeated message.
+ EXPECT_FALSE(
+ FieldMaskUtil::IsValidPath<TestAllTypes>("repeated_nested_message.bb"));
+}
+
+TEST(FieldMaskUtilTest, TestIsValidFieldMask) {
+ FieldMask mask;
+ FieldMaskUtil::FromString("optional_int32,optional_nested_message.bb", &mask);
+ EXPECT_TRUE(FieldMaskUtil::IsValidFieldMask<TestAllTypes>(mask));
+
+ FieldMaskUtil::FromString(
+ "optional_int32,optional_nested_message.bb,optional_nonexist", &mask);
+ EXPECT_FALSE(FieldMaskUtil::IsValidFieldMask<TestAllTypes>(mask));
+}
+
+TEST(FieldMaskUtilTest, TestGetFieldMaskForAllFields) {
+ FieldMask mask;
+ FieldMaskUtil::GetFieldMaskForAllFields<TestAllTypes::NestedMessage>(&mask);
+ EXPECT_EQ(1, mask.paths_size());
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("bb", mask));
+
+ FieldMaskUtil::GetFieldMaskForAllFields<TestAllTypes>(&mask);
+ EXPECT_EQ(76, mask.paths_size());
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_int32", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_int64", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_uint32", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_uint64", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sint32", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sint64", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_fixed32", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_fixed64", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sfixed32", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sfixed64", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_float", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_double", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_bool", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_string", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_bytes", mask));
+ EXPECT_TRUE(
+ FieldMaskUtil::IsPathInFieldMask("optional_nested_message", mask));
+ EXPECT_TRUE(
+ FieldMaskUtil::IsPathInFieldMask("optional_foreign_message", mask));
+ EXPECT_TRUE(
+ FieldMaskUtil::IsPathInFieldMask("optional_import_message", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_nested_enum", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_foreign_enum", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_import_enum", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_int32", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_int64", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_uint32", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_uint64", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sint32", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sint64", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_fixed32", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_fixed64", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sfixed32", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sfixed64", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_float", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_double", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_bool", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_string", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_bytes", mask));
+ EXPECT_TRUE(
+ FieldMaskUtil::IsPathInFieldMask("repeated_nested_message", mask));
+ EXPECT_TRUE(
+ FieldMaskUtil::IsPathInFieldMask("repeated_foreign_message", mask));
+ EXPECT_TRUE(
+ FieldMaskUtil::IsPathInFieldMask("repeated_import_message", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_nested_enum", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_foreign_enum", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_import_enum", mask));
+}
+
+TEST(FieldMaskUtilTest, TestToCanonicalForm) {
+ FieldMask in, out;
+ // Paths will be sorted.
+ FieldMaskUtil::FromString("baz.quz,bar,foo", &in);
+ FieldMaskUtil::ToCanonicalForm(in, &out);
+ EXPECT_EQ("bar,baz.quz,foo", FieldMaskUtil::ToString(out));
+ // Duplicated paths will be removed.
+ FieldMaskUtil::FromString("foo,bar,foo", &in);
+ FieldMaskUtil::ToCanonicalForm(in, &out);
+ EXPECT_EQ("bar,foo", FieldMaskUtil::ToString(out));
+ // Sub-paths of other paths will be removed.
+ FieldMaskUtil::FromString("foo.b1,bar.b1,foo.b2,bar", &in);
+ FieldMaskUtil::ToCanonicalForm(in, &out);
+ EXPECT_EQ("bar,foo.b1,foo.b2", FieldMaskUtil::ToString(out));
+
+ // Test more deeply nested cases.
+ FieldMaskUtil::FromString(
+ "foo.bar.baz1,"
+ "foo.bar.baz2.quz,"
+ "foo.bar.baz2",
+ &in);
+ FieldMaskUtil::ToCanonicalForm(in, &out);
+ EXPECT_EQ("foo.bar.baz1,foo.bar.baz2", FieldMaskUtil::ToString(out));
+ FieldMaskUtil::FromString(
+ "foo.bar.baz1,"
+ "foo.bar.baz2,"
+ "foo.bar.baz2.quz",
+ &in);
+ FieldMaskUtil::ToCanonicalForm(in, &out);
+ EXPECT_EQ("foo.bar.baz1,foo.bar.baz2", FieldMaskUtil::ToString(out));
+ FieldMaskUtil::FromString(
+ "foo.bar.baz1,"
+ "foo.bar.baz2,"
+ "foo.bar.baz2.quz,"
+ "foo.bar",
+ &in);
+ FieldMaskUtil::ToCanonicalForm(in, &out);
+ EXPECT_EQ("foo.bar", FieldMaskUtil::ToString(out));
+ FieldMaskUtil::FromString(
+ "foo.bar.baz1,"
+ "foo.bar.baz2,"
+ "foo.bar.baz2.quz,"
+ "foo",
+ &in);
+ FieldMaskUtil::ToCanonicalForm(in, &out);
+ EXPECT_EQ("foo", FieldMaskUtil::ToString(out));
+}
+
+TEST(FieldMaskUtilTest, TestUnion) {
+ FieldMask mask1, mask2, out;
+ // Test cases without overlapping.
+ FieldMaskUtil::FromString("foo,baz", &mask1);
+ FieldMaskUtil::FromString("bar,quz", &mask2);
+ FieldMaskUtil::Union(mask1, mask2, &out);
+ EXPECT_EQ("bar,baz,foo,quz", FieldMaskUtil::ToString(out));
+ // Overlap with duplicated paths.
+ FieldMaskUtil::FromString("foo,baz.bb", &mask1);
+ FieldMaskUtil::FromString("baz.bb,quz", &mask2);
+ FieldMaskUtil::Union(mask1, mask2, &out);
+ EXPECT_EQ("baz.bb,foo,quz", FieldMaskUtil::ToString(out));
+ // Overlap with paths covering some other paths.
+ FieldMaskUtil::FromString("foo.bar.baz,quz", &mask1);
+ FieldMaskUtil::FromString("foo.bar,bar", &mask2);
+ FieldMaskUtil::Union(mask1, mask2, &out);
+ EXPECT_EQ("bar,foo.bar,quz", FieldMaskUtil::ToString(out));
+}
+
+TEST(FieldMaskUtilTest, TestIntersect) {
+ FieldMask mask1, mask2, out;
+ // Test cases without overlapping.
+ FieldMaskUtil::FromString("foo,baz", &mask1);
+ FieldMaskUtil::FromString("bar,quz", &mask2);
+ FieldMaskUtil::Intersect(mask1, mask2, &out);
+ EXPECT_EQ("", FieldMaskUtil::ToString(out));
+ // Overlap with duplicated paths.
+ FieldMaskUtil::FromString("foo,baz.bb", &mask1);
+ FieldMaskUtil::FromString("baz.bb,quz", &mask2);
+ FieldMaskUtil::Intersect(mask1, mask2, &out);
+ EXPECT_EQ("baz.bb", FieldMaskUtil::ToString(out));
+ // Overlap with paths covering some other paths.
+ FieldMaskUtil::FromString("foo.bar.baz,quz", &mask1);
+ FieldMaskUtil::FromString("foo.bar,bar", &mask2);
+ FieldMaskUtil::Intersect(mask1, mask2, &out);
+ EXPECT_EQ("foo.bar.baz", FieldMaskUtil::ToString(out));
+}
+
+TEST(FieldMaskUtilTest, TestIspathInFieldMask) {
+ FieldMask mask;
+ FieldMaskUtil::FromString("foo.bar", &mask);
+ EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("", mask));
+ EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("foo", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("foo.bar", mask));
+ EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("foo.bar.baz", mask));
+ EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("foo.bar0.baz", mask));
+}
+
+TEST(FieldMaskUtilTest, MergeMessage) {
+ TestAllTypes src, dst;
+ TestUtil::SetAllFields(&src);
+ FieldMaskUtil::MergeOptions options;
+
+#define TEST_MERGE_ONE_PRIMITIVE_FIELD(field_name) \
+ { \
+ TestAllTypes tmp; \
+ tmp.set_##field_name(src.field_name()); \
+ FieldMask mask; \
+ mask.add_paths(#field_name); \
+ dst.Clear(); \
+ FieldMaskUtil::MergeMessageTo(src, mask, options, &dst); \
+ EXPECT_EQ(tmp.DebugString(), dst.DebugString()); \
+ }
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_int32)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_int64)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_uint32)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_uint64)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sint32)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sint64)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_fixed32)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_fixed64)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sfixed32)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sfixed64)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_float)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_double)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_bool)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_string)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_bytes)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_nested_enum)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_foreign_enum)
+ TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_import_enum)
+#undef TEST_MERGE_ONE_PRIMITIVE_FIELD
+
+#define TEST_MERGE_ONE_FIELD(field_name) \
+ { \
+ TestAllTypes tmp; \
+ *tmp.mutable_##field_name() = src.field_name(); \
+ FieldMask mask; \
+ mask.add_paths(#field_name); \
+ dst.Clear(); \
+ FieldMaskUtil::MergeMessageTo(src, mask, options, &dst); \
+ EXPECT_EQ(tmp.DebugString(), dst.DebugString()); \
+ }
+ TEST_MERGE_ONE_FIELD(optional_nested_message)
+ TEST_MERGE_ONE_FIELD(optional_foreign_message)
+ TEST_MERGE_ONE_FIELD(optional_import_message)
+
+ TEST_MERGE_ONE_FIELD(repeated_int32)
+ TEST_MERGE_ONE_FIELD(repeated_int64)
+ TEST_MERGE_ONE_FIELD(repeated_uint32)
+ TEST_MERGE_ONE_FIELD(repeated_uint64)
+ TEST_MERGE_ONE_FIELD(repeated_sint32)
+ TEST_MERGE_ONE_FIELD(repeated_sint64)
+ TEST_MERGE_ONE_FIELD(repeated_fixed32)
+ TEST_MERGE_ONE_FIELD(repeated_fixed64)
+ TEST_MERGE_ONE_FIELD(repeated_sfixed32)
+ TEST_MERGE_ONE_FIELD(repeated_sfixed64)
+ TEST_MERGE_ONE_FIELD(repeated_float)
+ TEST_MERGE_ONE_FIELD(repeated_double)
+ TEST_MERGE_ONE_FIELD(repeated_bool)
+ TEST_MERGE_ONE_FIELD(repeated_string)
+ TEST_MERGE_ONE_FIELD(repeated_bytes)
+ TEST_MERGE_ONE_FIELD(repeated_nested_message)
+ TEST_MERGE_ONE_FIELD(repeated_foreign_message)
+ TEST_MERGE_ONE_FIELD(repeated_import_message)
+ TEST_MERGE_ONE_FIELD(repeated_nested_enum)
+ TEST_MERGE_ONE_FIELD(repeated_foreign_enum)
+ TEST_MERGE_ONE_FIELD(repeated_import_enum)
+#undef TEST_MERGE_ONE_FIELD
+
+ // Test merge nested fields.
+ NestedTestAllTypes nested_src, nested_dst;
+ nested_src.mutable_child()->mutable_payload()->set_optional_int32(1234);
+ nested_src.mutable_child()
+ ->mutable_child()
+ ->mutable_payload()
+ ->set_optional_int32(5678);
+ FieldMask mask;
+ FieldMaskUtil::FromString("child.payload", &mask);
+ FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+ EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
+ EXPECT_EQ(0, nested_dst.child().child().payload().optional_int32());
+
+ FieldMaskUtil::FromString("child.child.payload", &mask);
+ FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+ EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
+ EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
+
+ nested_dst.Clear();
+ FieldMaskUtil::FromString("child.child.payload", &mask);
+ FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+ EXPECT_EQ(0, nested_dst.child().payload().optional_int32());
+ EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
+
+ nested_dst.Clear();
+ FieldMaskUtil::FromString("child", &mask);
+ FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+ EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
+ EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
+
+ // Test MergeOptions.
+
+ nested_dst.Clear();
+ nested_dst.mutable_child()->mutable_payload()->set_optional_int64(4321);
+ // Message fields will be merged by default.
+ FieldMaskUtil::FromString("child.payload", &mask);
+ FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+ EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
+ EXPECT_EQ(4321, nested_dst.child().payload().optional_int64());
+ // Change the behavior to replace message fields.
+ options.set_replace_message_fields(true);
+ FieldMaskUtil::FromString("child.payload", &mask);
+ FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+ EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
+ EXPECT_EQ(0, nested_dst.child().payload().optional_int64());
+
+ // By default, fields missing in source are not cleared in destination.
+ options.set_replace_message_fields(false);
+ nested_dst.mutable_payload();
+ EXPECT_TRUE(nested_dst.has_payload());
+ FieldMaskUtil::FromString("payload", &mask);
+ FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+ EXPECT_TRUE(nested_dst.has_payload());
+ // But they are cleared when replacing message fields.
+ options.set_replace_message_fields(true);
+ nested_dst.Clear();
+ nested_dst.mutable_payload();
+ FieldMaskUtil::FromString("payload", &mask);
+ FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+ EXPECT_FALSE(nested_dst.has_payload());
+
+ nested_src.mutable_payload()->add_repeated_int32(1234);
+ nested_dst.mutable_payload()->add_repeated_int32(5678);
+ // Repeated fields will be appended by default.
+ FieldMaskUtil::FromString("payload.repeated_int32", &mask);
+ FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+ ASSERT_EQ(2, nested_dst.payload().repeated_int32_size());
+ EXPECT_EQ(5678, nested_dst.payload().repeated_int32(0));
+ EXPECT_EQ(1234, nested_dst.payload().repeated_int32(1));
+ // Change the behavior to replace repeated fields.
+ options.set_replace_repeated_fields(true);
+ FieldMaskUtil::FromString("payload.repeated_int32", &mask);
+ FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
+ ASSERT_EQ(1, nested_dst.payload().repeated_int32_size());
+ EXPECT_EQ(1234, nested_dst.payload().repeated_int32(0));
+}
+
+
+} // namespace
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc
index 944fb2e3..ea360798 100644
--- a/src/google/protobuf/util/internal/datapiece.cc
+++ b/src/google/protobuf/util/internal/datapiece.cc
@@ -79,7 +79,9 @@ StatusOr<To> NumberConvertAndCheck(From before) {
// For conversion between double and float only.
template <typename To, typename From>
StatusOr<To> FloatingPointConvertAndCheck(From before) {
- if (MathLimits<From>::IsNaN(before)) return std::numeric_limits<To>::quiet_NaN();
+ if (MathLimits<From>::IsNaN(before)) {
+ return std::numeric_limits<To>::quiet_NaN();
+ }
To after = static_cast<To>(before);
if (MathUtil::AlmostEquals<To>(after, before)) {
@@ -167,7 +169,7 @@ StatusOr<string> DataPiece::ToString() const {
return str_.ToString();
case TYPE_BYTES: {
string base64;
- WebSafeBase64Escape(str_, &base64);
+ Base64Escape(str_, &base64);
return base64;
}
default:
diff --git a/src/google/protobuf/util/internal/datapiece.h b/src/google/protobuf/util/internal/datapiece.h
index 30947252..2ab3fa88 100644
--- a/src/google/protobuf/util/internal/datapiece.h
+++ b/src/google/protobuf/util/internal/datapiece.h
@@ -193,13 +193,13 @@ class LIBPROTOBUF_EXPORT DataPiece {
// Stored piece of data.
union {
- const int32 i32_;
- const int64 i64_;
- const uint32 u32_;
- const uint64 u64_;
- const double double_;
- const float float_;
- const bool bool_;
+ int32 i32_;
+ int64 i64_;
+ uint32 u32_;
+ uint64 u64_;
+ double double_;
+ float float_;
+ bool bool_;
StringPiecePod str_;
};
};
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc
index 267e2cd3..97b248ff 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.cc
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc
@@ -46,6 +46,7 @@ DefaultValueObjectWriter::DefaultValueObjectWriter(
TypeResolver* type_resolver, const google::protobuf::Type& type,
ObjectWriter* ow)
: typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
+ own_typeinfo_(true),
type_(type),
disable_normalize_(false),
current_(NULL),
@@ -56,6 +57,9 @@ DefaultValueObjectWriter::~DefaultValueObjectWriter() {
for (int i = 0; i < string_values_.size(); ++i) {
delete string_values_[i];
}
+ if (own_typeinfo_) {
+ delete typeinfo_;
+ }
}
DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBool(StringPiece name,
@@ -197,33 +201,47 @@ void DefaultValueObjectWriter::Node::WriteTo(ObjectWriter* ow) {
if (disable_normalize_) {
ow->DisableCaseNormalizationForNextKey();
}
+
if (kind_ == PRIMITIVE) {
ObjectWriter::RenderDataPieceTo(data_, name_, ow);
return;
}
- if (is_placeholder_) {
- // If is_placeholder_ = true, we didn't see this node in the response, so
- // skip output.
+
+ // Render maps. Empty maps are rendered as "{}".
+ if (kind_ == MAP) {
+ ow->StartObject(name_);
+ WriteChildren(ow);
+ ow->EndObject();
return;
}
+
+ // Write out lists. If we didn't have any list in response, write out empty
+ // list.
if (kind_ == LIST) {
ow->StartList(name_);
- } else {
- ow->StartObject(name_);
+ WriteChildren(ow);
+ ow->EndList();
+ return;
}
+
+ // If is_placeholder_ = true, we didn't see this node in the response, so
+ // skip output.
+ if (is_placeholder_) return;
+
+ ow->StartObject(name_);
+ WriteChildren(ow);
+ ow->EndObject();
+}
+
+void DefaultValueObjectWriter::Node::WriteChildren(ObjectWriter* ow) {
for (int i = 0; i < children_.size(); ++i) {
Node* child = children_[i];
child->WriteTo(ow);
}
- if (kind_ == LIST) {
- ow->EndList();
- } else {
- ow->EndObject();
- }
}
const google::protobuf::Type* DefaultValueObjectWriter::Node::GetMapValueType(
- const google::protobuf::Type& found_type, TypeInfo* typeinfo) {
+ const google::protobuf::Type& found_type, const TypeInfo* typeinfo) {
// If this field is a map, we should use the type of its "Value" as
// the type of the child node.
for (int i = 0; i < found_type.fields_size(); ++i) {
@@ -248,7 +266,8 @@ const google::protobuf::Type* DefaultValueObjectWriter::Node::GetMapValueType(
return NULL;
}
-void DefaultValueObjectWriter::Node::PopulateChildren(TypeInfo* typeinfo) {
+void DefaultValueObjectWriter::Node::PopulateChildren(
+ const TypeInfo* typeinfo) {
// Ignores well known types that don't require automatically populating their
// primitive children. For type "Any", we only populate its children when the
// "@type" field is set.
@@ -310,15 +329,17 @@ void DefaultValueObjectWriter::Node::PopulateChildren(TypeInfo* typeinfo) {
google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) {
kind = LIST;
}
- // If the child field is of primitive type, sets its data to the default
- // value of its type.
+
// If oneof_index() != 0, the child field is part of a "oneof", which means
// the child field is optional and we shouldn't populate its default value.
+ if (field.oneof_index() != 0) continue;
+
+ // If the child field is of primitive type, sets its data to the default
+ // value of its type.
google::protobuf::scoped_ptr<Node> child(
- new Node(field.name(), field_type, kind,
- ((kind == PRIMITIVE && field.oneof_index() == 0)
- ? CreateDefaultDataPieceForField(field)
- : DataPiece::NullData()),
+ new Node(field.json_name(), field_type, kind,
+ kind == PRIMITIVE ? CreateDefaultDataPieceForField(field)
+ : DataPiece::NullData(),
true));
new_children.push_back(child.release());
}
@@ -338,7 +359,7 @@ void DefaultValueObjectWriter::MaybePopulateChildrenOfAny(Node* node) {
// have been added, populates its children.
if (node != NULL && node->is_any() && node->type() != NULL &&
node->type()->name() != kAnyType && node->number_of_children() == 1) {
- node->PopulateChildren(typeinfo_.get());
+ node->PopulateChildren(typeinfo_);
}
}
@@ -388,7 +409,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(),
false));
root_->set_disable_normalize(GetAndResetDisableNormalize());
- root_->PopulateChildren(typeinfo_.get());
+ root_->PopulateChildren(typeinfo_);
current_ = root_.get();
return this;
}
@@ -409,7 +430,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
child->set_is_placeholder(false);
child->set_disable_normalize(GetAndResetDisableNormalize());
if (child->kind() == OBJECT && child->number_of_children() == 0) {
- child->PopulateChildren(typeinfo_.get());
+ child->PopulateChildren(typeinfo_);
}
stack_.push(current_);
@@ -492,12 +513,11 @@ void DefaultValueObjectWriter::RenderDataPiece(StringPiece name,
// first value field is rendered before we populate the children, because
// the "value" field of a Any message could be omitted.
if (current_->number_of_children() > 1 && current_->type() != NULL) {
- current_->PopulateChildren(typeinfo_.get());
+ current_->PopulateChildren(typeinfo_);
}
}
Node* child = current_->FindChild(name);
if (child == NULL || child->kind() != PRIMITIVE) {
- GOOGLE_LOG(WARNING) << "Cannot find primitive field '" << name << "'.";
// No children are found, creates a new child.
google::protobuf::scoped_ptr<Node> node(
new Node(name.ToString(), NULL, PRIMITIVE, data, false));
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h
index 759ba91b..d4547601 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.h
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.h
@@ -129,7 +129,7 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// Populates children of this Node based on its type. If there are already
// children created, they will be merged to the result. Caller should pass
// in TypeInfo for looking up types of the children.
- void PopulateChildren(TypeInfo* typeinfo);
+ void PopulateChildren(const TypeInfo* typeinfo);
// If this node is a leaf (has data), writes the current node to the
// ObjectWriter; if not, then recursively writes the children to the
@@ -165,7 +165,10 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// Returns the Value Type of a map given the Type of the map entry and a
// TypeInfo instance.
const google::protobuf::Type* GetMapValueType(
- const google::protobuf::Type& entry_type, TypeInfo* typeinfo);
+ const google::protobuf::Type& entry_type, const TypeInfo* typeinfo);
+
+ // Calls WriteTo() on every child in children_.
+ void WriteChildren(ObjectWriter* ow);
// The name of this node.
string name_;
@@ -210,7 +213,9 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// Type information for all the types used in the descriptor. Used to find
// google::protobuf::Type of nested messages/enums.
- google::protobuf::scoped_ptr<TypeInfo> typeinfo_;
+ const TypeInfo* typeinfo_;
+ // Whether the TypeInfo object is owned by this class.
+ bool own_typeinfo_;
// google::protobuf::Type of the root message type.
const google::protobuf::Type& type_;
// Holds copies of strings passed to RenderString.
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
index 593c7105..237d0722 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
@@ -73,15 +73,15 @@ INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
TEST_P(DefaultValueObjectWriterTest, Empty) {
// Set expectation
expects_.StartObject("")
- ->RenderDouble("double_value", 0.0)
- ->RenderFloat("float_value", 0.0)
- ->RenderInt64("int64_value", 0)
- ->RenderUint64("uint64_value", 0)
- ->RenderInt32("int32_value", 0)
- ->RenderUint32("uint32_value", 0)
- ->RenderBool("bool_value", false)
- ->RenderString("string_value", "")
- ->RenderBytes("bytes_value", "")
+ ->RenderDouble("doubleValue", 0.0)
+ ->RenderFloat("floatValue", 0.0)
+ ->RenderInt64("int64Value", 0)
+ ->RenderUint64("uint64Value", 0)
+ ->RenderInt32("int32Value", 0)
+ ->RenderUint32("uint32Value", 0)
+ ->RenderBool("boolValue", false)
+ ->RenderString("stringValue", "")
+ ->RenderBytes("bytesValue", "")
->EndObject();
// Actual testing
@@ -91,42 +91,42 @@ TEST_P(DefaultValueObjectWriterTest, Empty) {
TEST_P(DefaultValueObjectWriterTest, NonDefaultDouble) {
// Set expectation
expects_.StartObject("")
- ->RenderDouble("double_value", 1.0)
- ->RenderFloat("float_value", 0.0)
- ->RenderInt64("int64_value", 0)
- ->RenderUint64("uint64_value", 0)
- ->RenderInt32("int32_value", 0)
- ->RenderUint32("uint32_value", 0)
- ->RenderBool("bool_value", false)
- ->RenderString("string_value", "")
+ ->RenderDouble("doubleValue", 1.0)
+ ->RenderFloat("floatValue", 0.0)
+ ->RenderInt64("int64Value", 0)
+ ->RenderUint64("uint64Value", 0)
+ ->RenderInt32("int32Value", 0)
+ ->RenderUint32("uint32Value", 0)
+ ->RenderBool("boolValue", false)
+ ->RenderString("stringValue", "")
->EndObject();
// Actual testing
- testing_->StartObject("")->RenderDouble("double_value", 1.0)->EndObject();
+ testing_->StartObject("")->RenderDouble("doubleValue", 1.0)->EndObject();
}
TEST_P(DefaultValueObjectWriterTest, ShouldRetainUnknownField) {
// Set expectation
expects_.StartObject("")
- ->RenderDouble("double_value", 1.0)
- ->RenderFloat("float_value", 0.0)
- ->RenderInt64("int64_value", 0)
- ->RenderUint64("uint64_value", 0)
- ->RenderInt32("int32_value", 0)
- ->RenderUint32("uint32_value", 0)
- ->RenderBool("bool_value", false)
- ->RenderString("string_value", "")
+ ->RenderDouble("doubleValue", 1.0)
+ ->RenderFloat("floatValue", 0.0)
+ ->RenderInt64("int64Value", 0)
+ ->RenderUint64("uint64Value", 0)
+ ->RenderInt32("int32Value", 0)
+ ->RenderUint32("uint32Value", 0)
+ ->RenderBool("boolValue", false)
+ ->RenderString("stringValue", "")
->RenderString("unknown", "abc")
- ->StartObject("unknown_object")
+ ->StartObject("unknownObject")
->RenderString("unknown", "def")
->EndObject()
->EndObject();
// Actual testing
testing_->StartObject("")
- ->RenderDouble("double_value", 1.0)
+ ->RenderDouble("doubleValue", 1.0)
->RenderString("unknown", "abc")
- ->StartObject("unknown_object")
+ ->StartObject("unknownObject")
->RenderString("unknown", "def")
->EndObject()
->EndObject();
diff --git a/src/google/protobuf/util/internal/error_listener.h b/src/google/protobuf/util/internal/error_listener.h
index 9b907df5..2699684d 100644
--- a/src/google/protobuf/util/internal/error_listener.h
+++ b/src/google/protobuf/util/internal/error_listener.h
@@ -37,7 +37,9 @@
#endif
#include <string>
+#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/util/internal/location_tracker.h>
#include <google/protobuf/stubs/stringpiece.h>
diff --git a/src/google/protobuf/util/internal/field_mask_utility.cc b/src/google/protobuf/util/internal/field_mask_utility.cc
index 92468959..f0e8fc88 100644
--- a/src/google/protobuf/util/internal/field_mask_utility.cc
+++ b/src/google/protobuf/util/internal/field_mask_utility.cc
@@ -34,7 +34,6 @@
#include <google/protobuf/stubs/status_macros.h>
namespace google {
-
namespace protobuf {
namespace util {
namespace converter {
@@ -138,7 +137,7 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
}
// Un-escaped '"' must be followed with a ']'.
if (i >= length - 1 || paths[i + 1] != ']') {
- return CreatePublicError(
+ return util::Status(
util::error::INVALID_ARGUMENT,
StrCat("Invalid FieldMask '", paths,
"'. Map keys should be represented as [\"some_key\"]."));
@@ -150,7 +149,7 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
// Checks whether the key ends at the end of a path segment.
if (i < length - 1 && paths[i + 1] != '.' && paths[i + 1] != ',' &&
paths[i + 1] != ')' && paths[i + 1] != '(') {
- return CreatePublicError(
+ return util::Status(
util::error::INVALID_ARGUMENT,
StrCat("Invalid FieldMask '", paths,
"'. Map keys should be at the end of a path segment."));
@@ -162,7 +161,7 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
// We are not in a map key, look for the start of one.
if (paths[i] == '[') {
if (i >= length - 1 || paths[i + 1] != '\"') {
- return CreatePublicError(
+ return util::Status(
util::error::INVALID_ARGUMENT,
StrCat("Invalid FieldMask '", paths,
"'. Map keys should be represented as [\"some_key\"]."));
@@ -198,7 +197,7 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
// Removes the last prefix after seeing a ')'.
if (i < length && paths[i] == ')') {
if (prefix.empty()) {
- return CreatePublicError(
+ return util::Status(
util::error::INVALID_ARGUMENT,
StrCat("Invalid FieldMask '", paths,
"'. Cannot find matching '(' for all ')'."));
@@ -208,16 +207,14 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
previous_position = i + 1;
}
if (in_map_key) {
- return CreatePublicError(
- util::error::INVALID_ARGUMENT,
- StrCat("Invalid FieldMask '", paths,
- "'. Cannot find matching ']' for all '['."));
+ return util::Status(util::error::INVALID_ARGUMENT,
+ StrCat("Invalid FieldMask '", paths,
+ "'. Cannot find matching ']' for all '['."));
}
if (!prefix.empty()) {
- return CreatePublicError(
- util::error::INVALID_ARGUMENT,
- StrCat("Invalid FieldMask '", paths,
- "'. Cannot find matching ')' for all '('."));
+ return util::Status(util::error::INVALID_ARGUMENT,
+ StrCat("Invalid FieldMask '", paths,
+ "'. Cannot find matching ')' for all '('."));
}
return util::Status::OK;
}
diff --git a/src/google/protobuf/util/internal/json_escaping.cc b/src/google/protobuf/util/internal/json_escaping.cc
index 5ac23421..36dc8ef9 100644
--- a/src/google/protobuf/util/internal/json_escaping.cc
+++ b/src/google/protobuf/util/internal/json_escaping.cc
@@ -30,6 +30,7 @@
#include <google/protobuf/util/internal/json_escaping.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
namespace google {
diff --git a/src/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc
index 0c41515f..f81e3306 100644
--- a/src/google/protobuf/util/internal/json_objectwriter.cc
+++ b/src/google/protobuf/util/internal/json_objectwriter.cc
@@ -33,9 +33,11 @@
#include <math.h>
#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/util/internal/utility.h>
#include <google/protobuf/util/internal/json_escaping.h>
+#include <google/protobuf/stubs/mathlimits.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
@@ -114,7 +116,9 @@ JsonObjectWriter* JsonObjectWriter::RenderUint64(StringPiece name,
JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name,
double value) {
- if (isfinite(value)) return RenderSimple(name, SimpleDtoa(value));
+ if (google::protobuf::MathLimits<double>::IsFinite(value)) {
+ return RenderSimple(name, SimpleDtoa(value));
+ }
// Render quoted with NaN/Infinity-aware DoubleAsString.
return RenderString(name, DoubleAsString(value));
@@ -122,7 +126,9 @@ JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name,
JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name,
float value) {
- if (isfinite(value)) return RenderSimple(name, SimpleFtoa(value));
+ if (google::protobuf::MathLimits<float>::IsFinite(value)) {
+ return RenderSimple(name, SimpleFtoa(value));
+ }
// Render quoted with NaN/Infinity-aware FloatAsString.
return RenderString(name, FloatAsString(value));
@@ -142,7 +148,7 @@ JsonObjectWriter* JsonObjectWriter::RenderBytes(StringPiece name,
StringPiece value) {
WritePrefix(name);
string base64;
- WebSafeBase64EscapeWithPadding(value, &base64);
+ Base64Escape(value, &base64);
WriteChar('"');
// TODO(wpoon): Consider a ByteSink solution that writes the base64 bytes
// directly to the stream, rather than first putting them
diff --git a/src/google/protobuf/util/internal/json_objectwriter_test.cc b/src/google/protobuf/util/internal/json_objectwriter_test.cc
index df9a133e..dcd60601 100644
--- a/src/google/protobuf/util/internal/json_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/json_objectwriter_test.cc
@@ -47,7 +47,8 @@ class JsonObjectWriterTest : public ::testing::Test {
JsonObjectWriterTest()
: str_stream_(new StringOutputStream(&output_)),
out_stream_(new CodedOutputStream(str_stream_)),
- ow_(NULL) {}
+ ow_(NULL) {
+ }
virtual ~JsonObjectWriterTest() {
delete ow_;
@@ -63,34 +64,36 @@ class JsonObjectWriterTest : public ::testing::Test {
TEST_F(JsonObjectWriterTest, EmptyRootObject) {
ow_ = new JsonObjectWriter("", out_stream_);
- ow_->StartObject("")->EndObject();
+ ow_->StartObject("")
+ ->EndObject();
EXPECT_EQ("{}", output_.substr(0, out_stream_->ByteCount()));
}
TEST_F(JsonObjectWriterTest, EmptyObject) {
ow_ = new JsonObjectWriter("", out_stream_);
ow_->StartObject("")
- ->RenderString("test", "value")
- ->StartObject("empty")
- ->EndObject()
- ->EndObject();
+ ->RenderString("test", "value")
+ ->StartObject("empty")
+ ->EndObject()
+ ->EndObject();
EXPECT_EQ("{\"test\":\"value\",\"empty\":{}}",
output_.substr(0, out_stream_->ByteCount()));
}
TEST_F(JsonObjectWriterTest, EmptyRootList) {
ow_ = new JsonObjectWriter("", out_stream_);
- ow_->StartList("")->EndList();
+ ow_->StartList("")
+ ->EndList();
EXPECT_EQ("[]", output_.substr(0, out_stream_->ByteCount()));
}
TEST_F(JsonObjectWriterTest, EmptyList) {
ow_ = new JsonObjectWriter("", out_stream_);
ow_->StartObject("")
- ->RenderString("test", "value")
- ->StartList("empty")
- ->EndList()
- ->EndObject();
+ ->RenderString("test", "value")
+ ->StartList("empty")
+ ->EndList()
+ ->EndObject();
EXPECT_EQ("{\"test\":\"value\",\"empty\":[]}",
output_.substr(0, out_stream_->ByteCount()));
}
@@ -98,10 +101,10 @@ TEST_F(JsonObjectWriterTest, EmptyList) {
TEST_F(JsonObjectWriterTest, ObjectInObject) {
ow_ = new JsonObjectWriter("", out_stream_);
ow_->StartObject("")
- ->StartObject("nested")
- ->RenderString("field", "value")
- ->EndObject()
- ->EndObject();
+ ->StartObject("nested")
+ ->RenderString("field", "value")
+ ->EndObject()
+ ->EndObject();
EXPECT_EQ("{\"nested\":{\"field\":\"value\"}}",
output_.substr(0, out_stream_->ByteCount()));
}
@@ -109,10 +112,10 @@ TEST_F(JsonObjectWriterTest, ObjectInObject) {
TEST_F(JsonObjectWriterTest, ListInObject) {
ow_ = new JsonObjectWriter("", out_stream_);
ow_->StartObject("")
- ->StartList("nested")
- ->RenderString("", "value")
- ->EndList()
- ->EndObject();
+ ->StartList("nested")
+ ->RenderString("", "value")
+ ->EndList()
+ ->EndObject();
EXPECT_EQ("{\"nested\":[\"value\"]}",
output_.substr(0, out_stream_->ByteCount()));
}
@@ -120,10 +123,10 @@ TEST_F(JsonObjectWriterTest, ListInObject) {
TEST_F(JsonObjectWriterTest, ObjectInList) {
ow_ = new JsonObjectWriter("", out_stream_);
ow_->StartList("")
- ->StartObject("")
- ->RenderString("field", "value")
- ->EndObject()
- ->EndList();
+ ->StartObject("")
+ ->RenderString("field", "value")
+ ->EndObject()
+ ->EndList();
EXPECT_EQ("[{\"field\":\"value\"}]",
output_.substr(0, out_stream_->ByteCount()));
}
@@ -131,10 +134,10 @@ TEST_F(JsonObjectWriterTest, ObjectInList) {
TEST_F(JsonObjectWriterTest, ListInList) {
ow_ = new JsonObjectWriter("", out_stream_);
ow_->StartList("")
- ->StartList("")
- ->RenderString("", "value")
- ->EndList()
- ->EndList();
+ ->StartList("")
+ ->RenderString("", "value")
+ ->EndList()
+ ->EndList();
EXPECT_EQ("[[\"value\"]]", output_.substr(0, out_stream_->ByteCount()));
}
@@ -164,97 +167,95 @@ TEST_F(JsonObjectWriterTest, RenderPrimitives) {
output_.substr(0, out_stream_->ByteCount()));
}
-TEST_F(JsonObjectWriterTest, BytesEncodesAsWebSafeBase64) {
+TEST_F(JsonObjectWriterTest, BytesEncodesAsNonWebSafeBase64) {
string s;
s.push_back('\377');
s.push_back('\357');
ow_ = new JsonObjectWriter("", out_stream_);
ow_->StartObject("")->RenderBytes("bytes", s)->EndObject();
// Non-web-safe would encode this as "/+8="
- EXPECT_EQ("{\"bytes\":\"_-8=\"}",
+ EXPECT_EQ("{\"bytes\":\"/+8=\"}",
output_.substr(0, out_stream_->ByteCount()));
}
TEST_F(JsonObjectWriterTest, PrettyPrintList) {
ow_ = new JsonObjectWriter(" ", out_stream_);
ow_->StartObject("")
- ->StartList("items")
- ->RenderString("", "item1")
- ->RenderString("", "item2")
- ->RenderString("", "item3")
- ->EndList()
- ->StartList("empty")
- ->EndList()
- ->EndObject();
- EXPECT_EQ(
- "{\n"
- " \"items\": [\n"
- " \"item1\",\n"
- " \"item2\",\n"
- " \"item3\"\n"
- " ],\n"
- " \"empty\": []\n"
- "}\n",
- output_.substr(0, out_stream_->ByteCount()));
+ ->StartList("items")
+ ->RenderString("", "item1")
+ ->RenderString("", "item2")
+ ->RenderString("", "item3")
+ ->EndList()
+ ->StartList("empty")
+ ->EndList()
+ ->EndObject();
+ EXPECT_EQ("{\n"
+ " \"items\": [\n"
+ " \"item1\",\n"
+ " \"item2\",\n"
+ " \"item3\"\n"
+ " ],\n"
+ " \"empty\": []\n"
+ "}\n",
+ output_.substr(0, out_stream_->ByteCount()));
}
TEST_F(JsonObjectWriterTest, PrettyPrintObject) {
ow_ = new JsonObjectWriter(" ", out_stream_);
ow_->StartObject("")
- ->StartObject("items")
- ->RenderString("key1", "item1")
- ->RenderString("key2", "item2")
- ->RenderString("key3", "item3")
- ->EndObject()
- ->StartObject("empty")
- ->EndObject()
- ->EndObject();
- EXPECT_EQ(
- "{\n"
- " \"items\": {\n"
- " \"key1\": \"item1\",\n"
- " \"key2\": \"item2\",\n"
- " \"key3\": \"item3\"\n"
- " },\n"
- " \"empty\": {}\n"
- "}\n",
- output_.substr(0, out_stream_->ByteCount()));
+ ->StartObject("items")
+ ->RenderString("key1", "item1")
+ ->RenderString("key2", "item2")
+ ->RenderString("key3", "item3")
+ ->EndObject()
+ ->StartObject("empty")
+ ->EndObject()
+ ->EndObject();
+ EXPECT_EQ("{\n"
+ " \"items\": {\n"
+ " \"key1\": \"item1\",\n"
+ " \"key2\": \"item2\",\n"
+ " \"key3\": \"item3\"\n"
+ " },\n"
+ " \"empty\": {}\n"
+ "}\n",
+ output_.substr(0, out_stream_->ByteCount()));
}
TEST_F(JsonObjectWriterTest, PrettyPrintEmptyObjectInEmptyList) {
ow_ = new JsonObjectWriter(" ", out_stream_);
ow_->StartObject("")
- ->StartList("list")
- ->StartObject("")
- ->EndObject()
- ->EndList()
- ->EndObject();
- EXPECT_EQ(
- "{\n"
- " \"list\": [\n"
- " {}\n"
- " ]\n"
- "}\n",
- output_.substr(0, out_stream_->ByteCount()));
+ ->StartList("list")
+ ->StartObject("")
+ ->EndObject()
+ ->EndList()
+ ->EndObject();
+ EXPECT_EQ("{\n"
+ " \"list\": [\n"
+ " {}\n"
+ " ]\n"
+ "}\n",
+ output_.substr(0, out_stream_->ByteCount()));
}
TEST_F(JsonObjectWriterTest, PrettyPrintDoubleIndent) {
ow_ = new JsonObjectWriter(" ", out_stream_);
ow_->StartObject("")
- ->RenderBool("bool", true)
- ->RenderInt32("int", 42)
- ->EndObject();
- EXPECT_EQ(
- "{\n"
- " \"bool\": true,\n"
- " \"int\": 42\n"
- "}\n",
- output_.substr(0, out_stream_->ByteCount()));
+ ->RenderBool("bool", true)
+ ->RenderInt32("int", 42)
+ ->EndObject();
+ EXPECT_EQ("{\n"
+ " \"bool\": true,\n"
+ " \"int\": 42\n"
+ "}\n",
+ output_.substr(0, out_stream_->ByteCount()));
}
TEST_F(JsonObjectWriterTest, StringsEscapedAndEnclosedInDoubleQuotes) {
ow_ = new JsonObjectWriter("", out_stream_);
- ow_->StartObject("")->RenderString("string", "'<>&amp;\\\"\r\n")->EndObject();
+ ow_->StartObject("")
+ ->RenderString("string", "'<>&amp;\\\"\r\n")
+ ->EndObject();
EXPECT_EQ("{\"string\":\"'\\u003c\\u003e&amp;\\\\\\\"\\r\\n\"}",
output_.substr(0, out_stream_->ByteCount()));
}
@@ -262,13 +263,13 @@ TEST_F(JsonObjectWriterTest, StringsEscapedAndEnclosedInDoubleQuotes) {
TEST_F(JsonObjectWriterTest, Stringification) {
ow_ = new JsonObjectWriter("", out_stream_);
ow_->StartObject("")
- ->RenderDouble("double_nan", std::numeric_limits<double>::quiet_NaN())
- ->RenderFloat("float_nan", std::numeric_limits<float>::quiet_NaN())
- ->RenderDouble("double_pos", std::numeric_limits<double>::infinity())
- ->RenderFloat("float_pos", std::numeric_limits<float>::infinity())
- ->RenderDouble("double_neg", -std::numeric_limits<double>::infinity())
- ->RenderFloat("float_neg", -std::numeric_limits<float>::infinity())
- ->EndObject();
+ ->RenderDouble("double_nan", std::numeric_limits<double>::quiet_NaN())
+ ->RenderFloat("float_nan", std::numeric_limits<float>::quiet_NaN())
+ ->RenderDouble("double_pos", std::numeric_limits<double>::infinity())
+ ->RenderFloat("float_pos", std::numeric_limits<float>::infinity())
+ ->RenderDouble("double_neg", -std::numeric_limits<double>::infinity())
+ ->RenderFloat("float_neg", -std::numeric_limits<float>::infinity())
+ ->EndObject();
EXPECT_EQ(
"{\"double_nan\":\"NaN\","
"\"float_nan\":\"NaN\","
diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc
index d439a221..a7ef7fe2 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser.cc
@@ -40,6 +40,7 @@
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/util/internal/object_writer.h>
@@ -104,16 +105,42 @@ JsonStreamParser::JsonStreamParser(ObjectWriter* ow)
parsed_(),
parsed_storage_(),
string_open_(0),
- utf8_storage_(),
- utf8_length_(0) {
+ chunk_storage_(),
+ coerce_to_utf8_(false) {
// Initialize the stack with a single value to be parsed.
stack_.push(VALUE);
}
JsonStreamParser::~JsonStreamParser() {}
+
util::Status JsonStreamParser::Parse(StringPiece json) {
- return ParseChunk(json);
+ StringPiece chunk = json;
+ // If we have leftovers from a previous chunk, append the new chunk to it
+ // and create a new StringPiece pointing at the string's data. This could
+ // be large but we rely on the chunks to be small, assuming they are
+ // fragments of a Cord.
+ if (!leftover_.empty()) {
+ // Don't point chunk to leftover_ because leftover_ will be updated in
+ // ParseChunk(chunk).
+ chunk_storage_.swap(leftover_);
+ json.AppendToString(&chunk_storage_);
+ chunk = StringPiece(chunk_storage_);
+ }
+
+ // Find the structurally valid UTF8 prefix and parse only that.
+ int n = internal::UTF8SpnStructurallyValid(chunk);
+ if (n > 0) {
+ util::Status status = ParseChunk(chunk.substr(0, n));
+
+ // Any leftover characters are stashed in leftover_ for later parsing when
+ // there is more data available.
+ chunk.substr(n).AppendToString(&leftover_);
+ return status;
+ } else {
+ chunk.CopyToString(&leftover_);
+ return util::Status::OK;
+ }
}
util::Status JsonStreamParser::FinishParse() {
@@ -122,9 +149,22 @@ util::Status JsonStreamParser::FinishParse() {
if (stack_.empty() && leftover_.empty()) {
return util::Status::OK;
}
+
+ // Storage for UTF8-coerced string.
+ google::protobuf::scoped_array<char> utf8;
+ if (coerce_to_utf8_) {
+ utf8.reset(new char[leftover_.size()]);
+ char* coerced = internal::UTF8CoerceToStructurallyValid(leftover_, utf8.get(), ' ');
+ p_ = json_ = StringPiece(coerced, leftover_.size());
+ } else {
+ if (!internal::IsStructurallyValidUTF8(leftover_)) {
+ return ReportFailure("Encountered non UTF-8 code points.");
+ }
+ p_ = json_ = leftover_;
+ }
+
// Parse the remainder in finishing mode, which reports errors for things like
// unterminated strings or unknown tokens that would normally be retried.
- p_ = json_ = StringPiece(leftover_);
finishing_ = true;
util::Status result = RunParser();
if (result.ok()) {
@@ -137,16 +177,10 @@ util::Status JsonStreamParser::FinishParse() {
}
util::Status JsonStreamParser::ParseChunk(StringPiece chunk) {
- // If we have leftovers from a previous chunk, append the new chunk to it and
- // create a new StringPiece pointing at the string's data. This could be
- // large but we rely on the chunks to be small, assuming they are fragments
- // of a Cord.
- if (!leftover_.empty()) {
- chunk.AppendToString(&leftover_);
- p_ = json_ = StringPiece(leftover_);
- } else {
- p_ = json_ = chunk;
- }
+ // Do not do any work if the chunk is empty.
+ if (chunk.empty()) return util::Status::OK;
+
+ p_ = json_ = chunk;
finishing_ = false;
util::Status result = RunParser();
diff --git a/src/google/protobuf/util/internal/json_stream_parser.h b/src/google/protobuf/util/internal/json_stream_parser.h
index 17b094ae..0278c28f 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.h
+++ b/src/google/protobuf/util/internal/json_stream_parser.h
@@ -75,12 +75,14 @@ class LIBPROTOBUF_EXPORT JsonStreamParser {
explicit JsonStreamParser(ObjectWriter* ow);
virtual ~JsonStreamParser();
- // Parse a JSON string (UTF-8 encoded).
+ // Parses a UTF-8 encoded JSON string from a StringPiece.
util::Status Parse(StringPiece json);
+
// Finish parsing the JSON string.
util::Status FinishParse();
+
private:
enum TokenType {
BEGIN_STRING, // " or '
@@ -239,11 +241,11 @@ class LIBPROTOBUF_EXPORT JsonStreamParser {
// A value of 0 indicates that string parsing is not in process.
char string_open_;
- // Storage for utf8-coerced bytes.
- google::protobuf::scoped_array<char> utf8_storage_;
+ // Storage for the chunk that are being parsed in ParseChunk().
+ string chunk_storage_;
- // Length of the storage for utf8-coerced bytes.
- int utf8_length_;
+ // Whether to allow non UTF-8 encoded input and replace invalid code points.
+ bool coerce_to_utf8_;
GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonStreamParser);
};
diff --git a/src/google/protobuf/util/internal/json_stream_parser_test.cc b/src/google/protobuf/util/internal/json_stream_parser_test.cc
index b0775a2f..c833ed1f 100644
--- a/src/google/protobuf/util/internal/json_stream_parser_test.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc
@@ -30,6 +30,7 @@
#include <google/protobuf/util/internal/json_stream_parser.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/time.h>
#include <google/protobuf/util/internal/expecting_objectwriter.h>
@@ -85,7 +86,7 @@ class JsonStreamParserTest : public ::testing::Test {
JsonStreamParserTest() : mock_(), ow_(&mock_) {}
virtual ~JsonStreamParserTest() {}
- util::Status RunTest(StringPiece json, int split) {
+ util::Status RunTest(StringPiece json, int split, bool coerce_utf8 = false) {
JsonStreamParser parser(&mock_);
// Special case for split == length, test parsing one character at a time.
@@ -115,8 +116,8 @@ class JsonStreamParserTest : public ::testing::Test {
return result;
}
- void DoTest(StringPiece json, int split) {
- util::Status result = RunTest(json, split);
+ void DoTest(StringPiece json, int split, bool coerce_utf8 = false) {
+ util::Status result = RunTest(json, split, coerce_utf8);
if (!result.ok()) {
GOOGLE_LOG(WARNING) << result;
}
@@ -337,14 +338,26 @@ TEST_F(JsonStreamParserTest, ObjectValues) {
}
}
+
+TEST_F(JsonStreamParserTest, RejectNonUtf8WhenNotCoerced) {
+ StringPiece json = "{\"address\":\xFF\"חרושת 23, רעננה, ישראל\"}";
+ for (int i = 0; i <= json.length(); ++i) {
+ DoErrorTest(json, i, "Encountered non UTF-8 code points.");
+ }
+ json = "{\"address\": \"חרושת 23,\xFFרעננה, ישראל\"}";
+ for (int i = 0; i <= json.length(); ++i) {
+ DoErrorTest(json, i, "Encountered non UTF-8 code points.");
+ }
+}
+
#ifndef _MSC_VER
// - unicode handling in strings
TEST_F(JsonStreamParserTest, UnicodeEscaping) {
StringPiece str = "[\"\\u0639\\u0631\\u0628\\u0649\"]";
for (int i = 0; i <= str.length(); ++i) {
// TODO(xiaofeng): Figure out what default encoding to use for JSON strings.
- // In protobuf we use UTF-8 for strings, but for JSON we probably should allow
- // different encodings?
+ // In protobuf we use UTF-8 for strings, but for JSON we probably should
+ // allow different encodings?
ow_.StartList("")->RenderString("", "\u0639\u0631\u0628\u0649")->EndList();
DoTest(str, i);
}
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc
index 53a0e47a..996e1f8c 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource.cc
@@ -33,6 +33,7 @@
#include <utility>
#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/stubs/time.h>
@@ -46,6 +47,7 @@
#include <google/protobuf/util/internal/utility.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/once.h>
#include <google/protobuf/stubs/status_macros.h>
@@ -96,7 +98,7 @@ ProtoStreamObjectSource::ProtoStreamObjectSource(
}
ProtoStreamObjectSource::ProtoStreamObjectSource(
- google::protobuf::io::CodedInputStream* stream, TypeInfo* typeinfo,
+ google::protobuf::io::CodedInputStream* stream, const TypeInfo* typeinfo,
const google::protobuf::Type& type)
: stream_(stream), typeinfo_(typeinfo), own_typeinfo_(false), type_(type) {
GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL.";
@@ -156,7 +158,7 @@ Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type,
last_tag = tag;
field = FindAndVerifyField(type, tag);
if (field != NULL) {
- field_name = field->name();
+ field_name = field->json_name();
}
}
if (field == NULL) {
@@ -214,7 +216,7 @@ StatusOr<uint32> ProtoStreamObjectSource::RenderMap(
const google::protobuf::Field* field, StringPiece name, uint32 list_tag,
ObjectWriter* ow) const {
const google::protobuf::Type* field_type =
- typeinfo_->GetType(field->type_url());
+ typeinfo_->GetTypeByTypeUrl(field->type_url());
uint32 tag_to_return = 0;
if (IsPackable(*field) &&
list_tag ==
@@ -647,46 +649,53 @@ Status ProtoStreamObjectSource::RenderFieldMask(
}
hash_map<string, ProtoStreamObjectSource::TypeRenderer>*
-ProtoStreamObjectSource::CreateRendererMap() {
- hash_map<string, ProtoStreamObjectSource::TypeRenderer>* result =
- new hash_map<string, ProtoStreamObjectSource::TypeRenderer>();
- (*result)["google.protobuf.Timestamp"] =
+ ProtoStreamObjectSource::renderers_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(source_renderers_init_);
+
+void ProtoStreamObjectSource::InitRendererMap() {
+ renderers_ = new hash_map<string, ProtoStreamObjectSource::TypeRenderer>();
+ (*renderers_)["google.protobuf.Timestamp"] =
&ProtoStreamObjectSource::RenderTimestamp;
- (*result)["google.protobuf.Duration"] =
+ (*renderers_)["google.protobuf.Duration"] =
&ProtoStreamObjectSource::RenderDuration;
- (*result)["google.protobuf.DoubleValue"] =
+ (*renderers_)["google.protobuf.DoubleValue"] =
&ProtoStreamObjectSource::RenderDouble;
- (*result)["google.protobuf.FloatValue"] =
+ (*renderers_)["google.protobuf.FloatValue"] =
&ProtoStreamObjectSource::RenderFloat;
- (*result)["google.protobuf.Int64Value"] =
+ (*renderers_)["google.protobuf.Int64Value"] =
&ProtoStreamObjectSource::RenderInt64;
- (*result)["google.protobuf.UInt64Value"] =
+ (*renderers_)["google.protobuf.UInt64Value"] =
&ProtoStreamObjectSource::RenderUInt64;
- (*result)["google.protobuf.Int32Value"] =
+ (*renderers_)["google.protobuf.Int32Value"] =
&ProtoStreamObjectSource::RenderInt32;
- (*result)["google.protobuf.UInt32Value"] =
+ (*renderers_)["google.protobuf.UInt32Value"] =
&ProtoStreamObjectSource::RenderUInt32;
- (*result)["google.protobuf.BoolValue"] = &ProtoStreamObjectSource::RenderBool;
- (*result)["google.protobuf.StringValue"] =
+ (*renderers_)["google.protobuf.BoolValue"] = &ProtoStreamObjectSource::RenderBool;
+ (*renderers_)["google.protobuf.StringValue"] =
&ProtoStreamObjectSource::RenderString;
- (*result)["google.protobuf.BytesValue"] =
+ (*renderers_)["google.protobuf.BytesValue"] =
&ProtoStreamObjectSource::RenderBytes;
- (*result)["google.protobuf.Any"] = &ProtoStreamObjectSource::RenderAny;
- (*result)["google.protobuf.Struct"] = &ProtoStreamObjectSource::RenderStruct;
- (*result)["google.protobuf.Value"] =
+ (*renderers_)["google.protobuf.Any"] = &ProtoStreamObjectSource::RenderAny;
+ (*renderers_)["google.protobuf.Struct"] = &ProtoStreamObjectSource::RenderStruct;
+ (*renderers_)["google.protobuf.Value"] =
&ProtoStreamObjectSource::RenderStructValue;
- (*result)["google.protobuf.ListValue"] =
+ (*renderers_)["google.protobuf.ListValue"] =
&ProtoStreamObjectSource::RenderStructListValue;
- (*result)["google.protobuf.FieldMask"] =
+ (*renderers_)["google.protobuf.FieldMask"] =
&ProtoStreamObjectSource::RenderFieldMask;
- return result;
+ ::google::protobuf::internal::OnShutdown(&DeleteRendererMap);
+}
+
+void ProtoStreamObjectSource::DeleteRendererMap() {
+ delete ProtoStreamObjectSource::renderers_;
+ renderers_ = NULL;
}
// static
ProtoStreamObjectSource::TypeRenderer*
ProtoStreamObjectSource::FindTypeRenderer(const string& type_url) {
- static hash_map<string, TypeRenderer>* renderers = CreateRendererMap();
- return FindOrNull(*renderers, type_url);
+ ::google::protobuf::GoogleOnceInit(&source_renderers_init_, &InitRendererMap);
+ return FindOrNull(*renderers_, type_url);
}
Status ProtoStreamObjectSource::RenderField(
@@ -784,7 +793,8 @@ Status ProtoStreamObjectSource::RenderField(
// Get the nested enum type for this field.
// TODO(skarvaje): Avoid string manipulation. Find ways to speed this
// up.
- const google::protobuf::Enum* en = typeinfo_->GetEnum(field->type_url());
+ const google::protobuf::Enum* en =
+ typeinfo_->GetEnumByTypeUrl(field->type_url());
// Lookup the name of the enum, and render that. Skips unknown enums.
if (en != NULL) {
const google::protobuf::EnumValue* enum_value =
@@ -819,7 +829,7 @@ Status ProtoStreamObjectSource::RenderField(
int old_limit = stream_->PushLimit(buffer32);
// Get the nested message type for this field.
const google::protobuf::Type* type =
- typeinfo_->GetType(field->type_url());
+ typeinfo_->GetTypeByTypeUrl(field->type_url());
if (type == NULL) {
return Status(util::error::INTERNAL,
StrCat("Invalid configuration. Could not find the type: ",
@@ -928,7 +938,8 @@ const string ProtoStreamObjectSource::ReadFieldValueAsString(
// Get the nested enum type for this field.
// TODO(skarvaje): Avoid string manipulation. Find ways to speed this
// up.
- const google::protobuf::Enum* en = typeinfo_->GetEnum(field.type_url());
+ const google::protobuf::Enum* en =
+ typeinfo_->GetEnumByTypeUrl(field.type_url());
// Lookup the name of the enum, and render that. Skips unknown enums.
if (en != NULL) {
const google::protobuf::EnumValue* enum_value =
@@ -962,7 +973,7 @@ const string ProtoStreamObjectSource::ReadFieldValueAsString(
bool ProtoStreamObjectSource::IsMap(
const google::protobuf::Field& field) const {
const google::protobuf::Type* field_type =
- typeinfo_->GetType(field.type_url());
+ typeinfo_->GetTypeByTypeUrl(field.type_url());
// TODO(xiaofeng): Unify option names.
return field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE &&
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h
index 4a4e6bbf..f52383a1 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.h
+++ b/src/google/protobuf/util/internal/protostream_objectsource.h
@@ -46,7 +46,6 @@
#include <google/protobuf/stubs/statusor.h>
-
namespace google {
namespace protobuf {
class Field;
@@ -61,7 +60,10 @@ namespace converter {
class TypeInfo;
// An ObjectSource that can parse a stream of bytes as a protocol buffer.
-// This implementation uses a tech Type for tag lookup.
+// Its WriteTo() method can be given an ObjectWriter.
+// This implementation uses a google.protobuf.Type for tag and name lookup.
+// The field names are converted into lower camel-case when writing to the
+// ObjectWriter.
//
// Sample usage: (suppose input is: string proto)
// ArrayInputStream arr_stream(proto.data(), proto.size());
@@ -93,7 +95,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
private:
ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream,
- TypeInfo* typeinfo,
+ const TypeInfo* typeinfo,
const google::protobuf::Type& type);
// Function that renders a well known type with a modified behavior.
typedef util::Status (*TypeRenderer)(const ProtoStreamObjectSource*,
@@ -200,7 +202,9 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
const google::protobuf::Type& type,
StringPiece name, ObjectWriter* ow);
- static hash_map<string, TypeRenderer>* CreateRendererMap();
+ static hash_map<string, TypeRenderer>* renderers_;
+ static void InitRendererMap();
+ static void DeleteRendererMap();
static TypeRenderer* FindTypeRenderer(const string& type_url);
// Renders a field value to the ObjectWriter.
@@ -226,7 +230,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
// Type information for all the types used in the descriptor. Used to find
// google::protobuf::Type of nested messages/enums.
- TypeInfo* typeinfo_;
+ const TypeInfo* typeinfo_;
// Whether this class owns the typeinfo_ object. If true the typeinfo_ object
// should be deleted in the destructor.
bool own_typeinfo_;
diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
index 4cc62410..f6e5ee7a 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
@@ -117,61 +117,61 @@ class ProtostreamObjectSourceTest
void PrepareExpectingObjectWriterForRepeatedPrimitive() {
ow_.StartObject("")
- ->StartList("rep_fix32")
+ ->StartList("repFix32")
->RenderUint32("", bit_cast<uint32>(3201))
->RenderUint32("", bit_cast<uint32>(0))
->RenderUint32("", bit_cast<uint32>(3202))
->EndList()
- ->StartList("rep_u32")
+ ->StartList("repU32")
->RenderUint32("", bit_cast<uint32>(3203))
->RenderUint32("", bit_cast<uint32>(0))
->EndList()
- ->StartList("rep_i32")
+ ->StartList("repI32")
->RenderInt32("", 0)
->RenderInt32("", 3204)
->RenderInt32("", 3205)
->EndList()
- ->StartList("rep_sf32")
+ ->StartList("repSf32")
->RenderInt32("", 3206)
->RenderInt32("", 0)
->EndList()
- ->StartList("rep_s32")
+ ->StartList("repS32")
->RenderInt32("", 0)
->RenderInt32("", 3207)
->RenderInt32("", 3208)
->EndList()
- ->StartList("rep_fix64")
+ ->StartList("repFix64")
->RenderUint64("", bit_cast<uint64>(6401LL))
->RenderUint64("", bit_cast<uint64>(0LL))
->EndList()
- ->StartList("rep_u64")
+ ->StartList("repU64")
->RenderUint64("", bit_cast<uint64>(0LL))
->RenderUint64("", bit_cast<uint64>(6402LL))
->RenderUint64("", bit_cast<uint64>(6403LL))
->EndList()
- ->StartList("rep_i64")
+ ->StartList("repI64")
->RenderInt64("", 6404L)
->RenderInt64("", 0L)
->EndList()
- ->StartList("rep_sf64")
+ ->StartList("repSf64")
->RenderInt64("", 0L)
->RenderInt64("", 6405L)
->RenderInt64("", 6406L)
->EndList()
- ->StartList("rep_s64")
+ ->StartList("repS64")
->RenderInt64("", 6407L)
->RenderInt64("", 0L)
->EndList()
- ->StartList("rep_float")
+ ->StartList("repFloat")
->RenderFloat("", 0.0f)
->RenderFloat("", 32.1f)
->RenderFloat("", 32.2f)
->EndList()
- ->StartList("rep_double")
+ ->StartList("repDouble")
->RenderDouble("", 64.1L)
->RenderDouble("", 0.0L)
->EndList()
- ->StartList("rep_bool")
+ ->StartList("repBool")
->RenderBool("", true)
->RenderBool("", false)
->EndList()
@@ -317,11 +317,11 @@ TEST_P(ProtostreamObjectSourceTest, RepeatingPrimitives) {
primitive.add_rep_str("String Two");
primitive.add_rep_bytes("Some Bytes");
- ow_.StartList("rep_str")
+ ow_.StartList("repStr")
->RenderString("", "String One")
->RenderString("", "String Two")
->EndList()
- ->StartList("rep_bytes")
+ ->StartList("repBytes")
->RenderBytes("", "Some Bytes")
->EndList();
DoTest(primitive, Primitive::descriptor());
@@ -794,16 +794,16 @@ TEST_P(ProtostreamObjectSourceFieldMaskTest, FieldMaskRenderSuccess) {
ow_.StartObject("")
->RenderString("id", "1")
- ->RenderString("single_mask", "path1,snakeCasePath2")
- ->StartList("repeated_mask")
+ ->RenderString("singleMask", "path1,snakeCasePath2")
+ ->StartList("repeatedMask")
->RenderString("", "path3")
->RenderString("", "snakeCasePath4,path5")
->EndList()
- ->StartList("nested_mask")
+ ->StartList("nestedMask")
->StartObject("")
->RenderString("data", "data")
- ->RenderString("single_mask", "nested.path1,nestedField.snakeCasePath2")
- ->StartList("repeated_mask")
+ ->RenderString("singleMask", "nested.path1,nestedField.snakeCasePath2")
+ ->StartList("repeatedMask")
->RenderString("", "nestedField.path3,nested.snakeCasePath4")
->RenderString("", "nested.path5")
->RenderString("",
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
index 7f6f3c35..a935ac39 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -39,6 +39,7 @@
#include <google/protobuf/util/internal/object_location_tracker.h>
#include <google/protobuf/util/internal/constants.h>
#include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/stubs/once.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/statusor.h>
@@ -74,7 +75,7 @@ ProtoStreamObjectWriter::ProtoStreamObjectWriter(
tracker_(new ObjectLocationTracker()) {}
ProtoStreamObjectWriter::ProtoStreamObjectWriter(
- TypeInfo* typeinfo, const google::protobuf::Type& type,
+ const TypeInfo* typeinfo, const google::protobuf::Type& type,
strings::ByteSink* output, ErrorListener* listener)
: master_type_(type),
typeinfo_(typeinfo),
@@ -91,14 +92,19 @@ ProtoStreamObjectWriter::ProtoStreamObjectWriter(
tracker_(new ObjectLocationTracker()) {}
ProtoStreamObjectWriter::~ProtoStreamObjectWriter() {
- // Cleanup explicitly in order to avoid destructor stack overflow when input
- // is deeply nested.
- while (element_ != NULL) {
- element_.reset(element_->pop());
- }
if (own_typeinfo_) {
delete typeinfo_;
}
+ if (element_ == NULL) return;
+ // Cleanup explicitly in order to avoid destructor stack overflow when input
+ // is deeply nested.
+ // Cast to BaseElement to avoid doing additional checks (like missing fields)
+ // during pop().
+ google::protobuf::scoped_ptr<BaseElement> element(
+ static_cast<BaseElement*>(element_.get())->pop<BaseElement>());
+ while (element != NULL) {
+ element.reset(element->pop<BaseElement>());
+ }
}
namespace {
@@ -454,7 +460,7 @@ void ProtoStreamObjectWriter::AnyWriter::WriteAny() {
}
ProtoStreamObjectWriter::ProtoElement::ProtoElement(
- TypeInfo* typeinfo, const google::protobuf::Type& type,
+ const TypeInfo* typeinfo, const google::protobuf::Type& type,
ProtoStreamObjectWriter* enclosing)
: BaseElement(NULL),
ow_(enclosing),
@@ -586,6 +592,14 @@ string ProtoStreamObjectWriter::ProtoElement::ToString() const {
return loc.empty() ? "." : loc;
}
+bool ProtoStreamObjectWriter::ProtoElement::OneofIndexTaken(int32 index) {
+ return ContainsKey(oneof_indices_, index);
+}
+
+void ProtoStreamObjectWriter::ProtoElement::TakeOneofIndex(int32 index) {
+ InsertIfNotPresent(&oneof_indices_, index);
+}
+
inline void ProtoStreamObjectWriter::InvalidName(StringPiece unknown_name,
StringPiece message) {
listener_->InvalidName(location(), ToSnakeCase(unknown_name), message);
@@ -655,6 +669,13 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject(
return this;
}
+ // Check to see if this field is a oneof and that no oneof in that group has
+ // already been set.
+ if (!ValidOneof(*field, name)) {
+ ++invalid_depth_;
+ return this;
+ }
+
if (field->type_url() == GetFullTypeWithUrl(kStructType)) {
// Start a struct object.
StartStruct(field);
@@ -932,6 +953,14 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) {
// Also we ignore if the field is not found here as it is caught later.
field = typeinfo_->FindField(&element_->type(), name);
+ // Only check for oneof collisions on the first StartList call. We identify
+ // the first call with !name.empty() check. Subsequent list element calls
+ // will not have the name filled.
+ if (!name.empty() && field && !ValidOneof(*field, name)) {
+ ++invalid_depth_;
+ return this;
+ }
+
// It is an error to try to bind to map, which behind the scenes is a list.
if (field && IsMap(*field)) {
// Push field to stack for error location tracking & reporting.
@@ -1080,9 +1109,9 @@ Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow,
data.ValueAsStringOrDefault("")));
}
- // TODO(tsun): figure out how to do proto descriptor based snake case
- // conversions as much as possible. Because ToSnakeCase sometimes returns the
- // wrong value.
+// TODO(tsun): figure out how to do proto descriptor based snake case
+// conversions as much as possible. Because ToSnakeCase sometimes returns the
+// wrong value.
google::protobuf::scoped_ptr<ResultCallback1<util::Status, StringPiece> > callback(
NewPermanentCallback(&RenderOneFieldPath, ow));
return DecodeCompactFieldMaskPaths(data.str(), callback.get());
@@ -1154,6 +1183,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece(
const google::protobuf::Field* field = NULL;
string type_url;
bool is_map_entry = false;
+ // We are at the root when element_ == NULL.
if (element_ == NULL) {
type_url = GetFullTypeWithUrl(master_type_.name());
} else {
@@ -1166,6 +1196,11 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece(
if (field == NULL) {
return this;
}
+
+ // Check to see if this field is a oneof and that no oneof in that group has
+ // already been set.
+ if (!ValidOneof(*field, name)) return this;
+
type_url = field->type_url();
}
@@ -1314,7 +1349,8 @@ void ProtoStreamObjectWriter::RenderSimpleDataPiece(
}
case google::protobuf::Field_Kind_TYPE_ENUM: {
status = WriteEnum(field.number(), data,
- typeinfo_->GetEnum(field.type_url()), stream_.get());
+ typeinfo_->GetEnumByTypeUrl(field.type_url()),
+ stream_.get());
break;
}
default: // TYPE_GROUP or TYPE_MESSAGE
@@ -1330,60 +1366,67 @@ void ProtoStreamObjectWriter::RenderSimpleDataPiece(
// Map of functions that are responsible for rendering well known type
// represented by the key.
hash_map<string, ProtoStreamObjectWriter::TypeRenderer>*
-ProtoStreamObjectWriter::CreateRendererMap() {
- google::protobuf::scoped_ptr<hash_map<string, ProtoStreamObjectWriter::TypeRenderer> >
- result(new hash_map<string, ProtoStreamObjectWriter::TypeRenderer>());
- (*result)["type.googleapis.com/google.protobuf.Timestamp"] =
+ ProtoStreamObjectWriter::renderers_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(writer_renderers_init_);
+
+void ProtoStreamObjectWriter::InitRendererMap() {
+ renderers_ = new hash_map<string, ProtoStreamObjectWriter::TypeRenderer>();
+ (*renderers_)["type.googleapis.com/google.protobuf.Timestamp"] =
&ProtoStreamObjectWriter::RenderTimestamp;
- (*result)["type.googleapis.com/google.protobuf.Duration"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.Duration"] =
&ProtoStreamObjectWriter::RenderDuration;
- (*result)["type.googleapis.com/google.protobuf.FieldMask"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.FieldMask"] =
&ProtoStreamObjectWriter::RenderFieldMask;
- (*result)["type.googleapis.com/google.protobuf.Double"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.Double"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.Float"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.Float"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.Int64"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.Int64"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.UInt64"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.UInt64"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.Int32"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.Int32"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.UInt32"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.UInt32"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.Bool"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.Bool"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.String"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.String"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.Bytes"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.Bytes"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.DoubleValue"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.DoubleValue"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.FloatValue"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.FloatValue"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.Int64Value"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.Int64Value"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.UInt64Value"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.UInt64Value"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.Int32Value"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.Int32Value"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.UInt32Value"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.UInt32Value"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.BoolValue"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.BoolValue"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.StringValue"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.StringValue"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.BytesValue"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.BytesValue"] =
&ProtoStreamObjectWriter::RenderWrapperType;
- (*result)["type.googleapis.com/google.protobuf.Value"] =
+ (*renderers_)["type.googleapis.com/google.protobuf.Value"] =
&ProtoStreamObjectWriter::RenderStructValue;
- return result.release();
+ ::google::protobuf::internal::OnShutdown(&DeleteRendererMap);
+}
+
+void ProtoStreamObjectWriter::DeleteRendererMap() {
+ delete ProtoStreamObjectWriter::renderers_;
+ renderers_ = NULL;
}
ProtoStreamObjectWriter::TypeRenderer*
ProtoStreamObjectWriter::FindTypeRenderer(const string& type_url) {
- static hash_map<string, TypeRenderer>* renderers = CreateRendererMap();
- return FindOrNull(*renderers, type_url);
+ ::google::protobuf::GoogleOnceInit(&writer_renderers_init_, &InitRendererMap);
+ return FindOrNull(*renderers_, type_url);
}
ProtoStreamObjectWriter::ProtoElement::ElementType
@@ -1401,6 +1444,24 @@ ProtoStreamObjectWriter::GetElementType(const google::protobuf::Type& type) {
}
}
+bool ProtoStreamObjectWriter::ValidOneof(const google::protobuf::Field& field,
+ StringPiece unnormalized_name) {
+ if (element_ == NULL) return true;
+
+ if (field.oneof_index() > 0) {
+ if (element_->OneofIndexTaken(field.oneof_index())) {
+ InvalidValue(
+ "oneof",
+ StrCat("oneof field '",
+ element_->type().oneofs(field.oneof_index() - 1),
+ "' is already set. Cannot set '", unnormalized_name, "'"));
+ return false;
+ }
+ element_->TakeOneofIndex(field.oneof_index());
+ }
+ return true;
+}
+
const google::protobuf::Field* ProtoStreamObjectWriter::BeginNamed(
StringPiece name, bool is_list) {
if (invalid_depth_ > 0) {
@@ -1450,7 +1511,7 @@ const google::protobuf::Field* ProtoStreamObjectWriter::Lookup(
const google::protobuf::Type* ProtoStreamObjectWriter::LookupType(
const google::protobuf::Field* field) {
return (field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE
- ? typeinfo_->GetType(field->type_url())
+ ? typeinfo_->GetTypeByTypeUrl(field->type_url())
: &element_->type());
}
@@ -1539,7 +1600,7 @@ bool ProtoStreamObjectWriter::IsMap(const google::protobuf::Field& field) {
return false;
}
const google::protobuf::Type* field_type =
- typeinfo_->GetType(field.type_url());
+ typeinfo_->GetTypeByTypeUrl(field.type_url());
// TODO(xiaofeng): Unify option names.
return GetBoolOptionOrDefault(field_type->options(),
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h
index eb4a59f9..8f49120b 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.h
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.h
@@ -71,7 +71,7 @@ class ObjectLocationTracker;
// It also supports streaming.
class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter {
public:
- // Constructor. Does not take ownership of any parameter passed in.
+// Constructor. Does not take ownership of any parameter passed in.
ProtoStreamObjectWriter(TypeResolver* type_resolver,
const google::protobuf::Type& type,
strings::ByteSink* output, ErrorListener* listener);
@@ -82,20 +82,17 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
virtual ProtoStreamObjectWriter* EndObject();
virtual ProtoStreamObjectWriter* StartList(StringPiece name);
virtual ProtoStreamObjectWriter* EndList();
- virtual ProtoStreamObjectWriter* RenderBool(StringPiece name,
- bool value) {
+ virtual ProtoStreamObjectWriter* RenderBool(StringPiece name, bool value) {
return RenderDataPiece(name, DataPiece(value));
}
- virtual ProtoStreamObjectWriter* RenderInt32(StringPiece name,
- int32 value) {
+ virtual ProtoStreamObjectWriter* RenderInt32(StringPiece name, int32 value) {
return RenderDataPiece(name, DataPiece(value));
}
virtual ProtoStreamObjectWriter* RenderUint32(StringPiece name,
uint32 value) {
return RenderDataPiece(name, DataPiece(value));
}
- virtual ProtoStreamObjectWriter* RenderInt64(StringPiece name,
- int64 value) {
+ virtual ProtoStreamObjectWriter* RenderInt64(StringPiece name, int64 value) {
return RenderDataPiece(name, DataPiece(value));
}
virtual ProtoStreamObjectWriter* RenderUint64(StringPiece name,
@@ -106,8 +103,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
double value) {
return RenderDataPiece(name, DataPiece(value));
}
- virtual ProtoStreamObjectWriter* RenderFloat(StringPiece name,
- float value) {
+ virtual ProtoStreamObjectWriter* RenderFloat(StringPiece name, float value) {
return RenderDataPiece(name, DataPiece(value));
}
virtual ProtoStreamObjectWriter* RenderString(StringPiece name,
@@ -217,7 +213,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
};
// Constructor for the root element. No parent nor field.
- ProtoElement(TypeInfo* typeinfo, const google::protobuf::Type& type,
+ ProtoElement(const TypeInfo* typeinfo, const google::protobuf::Type& type,
ProtoStreamObjectWriter* enclosing);
// Constructor for a field of an element.
@@ -256,6 +252,13 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
return static_cast<ProtoElement*>(BaseElement::parent());
}
+ // Returns true if the index is already taken by a preceeding oneof input.
+ bool OneofIndexTaken(int32 index);
+
+ // Marks the oneof 'index' as taken. Future inputs to this oneof will
+ // generate an error.
+ void TakeOneofIndex(int32 index);
+
private:
// Used for access to variables of the enclosing instance of
// ProtoStreamObjectWriter.
@@ -269,7 +272,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
const google::protobuf::Field* field_;
// TypeInfo to lookup types.
- TypeInfo* typeinfo_;
+ const TypeInfo* typeinfo_;
// Additional variables if this element is a message:
// (Root element is always a message).
@@ -289,6 +292,10 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
// The type of this element, see enum for permissible types.
ElementType element_type_;
+ // Set of oneof indices already seen for the type_. Used to validate
+ // incoming messages so no more than one oneof is set.
+ hash_set<int32> oneof_indices_;
+
GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoElement);
};
@@ -298,7 +305,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
int size;
};
- ProtoStreamObjectWriter(TypeInfo* typeinfo,
+ ProtoStreamObjectWriter(const TypeInfo* typeinfo,
const google::protobuf::Type& type,
strings::ByteSink* output, ErrorListener* listener);
@@ -400,18 +407,28 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
// Helper functions to create the map and find functions responsible for
// rendering well known types, keyed by type URL.
- static hash_map<string, TypeRenderer>* CreateRendererMap();
+ static hash_map<string, TypeRenderer>* renderers_;
+ static void InitRendererMap();
+ static void DeleteRendererMap();
static TypeRenderer* FindTypeRenderer(const string& type_url);
// Returns the ProtoElement::ElementType for the given Type.
static ProtoElement::ElementType GetElementType(
const google::protobuf::Type& type);
+ // Returns true if the field for type_ can be set as a oneof. If field is not
+ // a oneof type, this function does nothing and returns true.
+ // If another field for this oneof is already set, this function returns
+ // false. It also calls the appropriate error callback.
+ // unnormalized_name is used for error string.
+ bool ValidOneof(const google::protobuf::Field& field,
+ StringPiece unnormalized_name);
+
// Variables for describing the structure of the input tree:
// master_type_: descriptor for the whole protobuf message.
// typeinfo_ : the TypeInfo object to lookup types.
const google::protobuf::Type& master_type_;
- TypeInfo* typeinfo_;
+ const TypeInfo* typeinfo_;
// Whether we own the typeinfo_ object.
bool own_typeinfo_;
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
index bd4f29f5..96e5ccfb 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
@@ -49,6 +49,7 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/util/internal/testdata/anys.pb.h>
#include <google/protobuf/util/internal/testdata/maps.pb.h>
+#include <google/protobuf/util/internal/testdata/oneofs.pb.h>
#include <google/protobuf/util/internal/testdata/struct.pb.h>
#include <google/protobuf/util/internal/testdata/timestamp_duration.pb.h>
#include <gtest/gtest.h>
@@ -75,6 +76,7 @@ using ::testing::_;
using ::testing::Args;
using google::protobuf::testing::anys::AnyM;
using google::protobuf::testing::anys::AnyOut;
+using google::protobuf::testing::oneofs::OneOfsRequest;
using google::protobuf::testing::FieldMaskTest;
using google::protobuf::testing::maps::MapIn;
using google::protobuf::testing::structs::StructType;
@@ -143,7 +145,7 @@ class BaseProtoStreamObjectWriterTest
void CheckOutput(const Message& expected) { CheckOutput(expected, -1); }
const google::protobuf::Type* GetType(const Descriptor* descriptor) {
- return helper_.GetTypeInfo()->GetType(GetTypeUrl(descriptor));
+ return helper_.GetTypeInfo()->GetTypeByTypeUrl(GetTypeUrl(descriptor));
}
testing::TypeInfoTestHelper helper_;
@@ -854,11 +856,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError1) {
EXPECT_CALL(
listener_,
- InvalidValue(_,
- StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
- StringPiece(
- "Field 'ts', Illegal timestamp format; timestamps "
- "must end with 'Z'")));
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+ StringPiece("Field 'ts', Illegal timestamp format; timestamps "
+ "must end with 'Z'")));
ow_->StartObject("")->RenderString("ts", "")->EndObject();
CheckOutput(timestamp);
@@ -883,11 +884,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError3) {
EXPECT_CALL(
listener_,
- InvalidValue(_,
- StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
- StringPiece(
- "Field 'ts', Invalid time format, failed to parse nano "
- "seconds")));
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+ StringPiece("Field 'ts', Invalid time format, failed to parse nano "
+ "seconds")));
ow_->StartObject("")
->RenderString("ts", "1970-01-01T00:00:00.ABZ")
@@ -919,11 +919,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError1) {
EXPECT_CALL(
listener_,
- InvalidValue(_,
- StringPiece("type.googleapis.com/google.protobuf.Duration"),
- StringPiece(
- "Field 'dur', Illegal duration format; duration must "
- "end with 's'")));
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
+ StringPiece("Field 'dur', Illegal duration format; duration must "
+ "end with 's'")));
ow_->StartObject("")->RenderString("dur", "")->EndObject();
CheckOutput(duration);
@@ -934,11 +933,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError2) {
EXPECT_CALL(
listener_,
- InvalidValue(_,
- StringPiece("type.googleapis.com/google.protobuf.Duration"),
- StringPiece(
- "Field 'dur', Invalid duration format, failed to parse "
- "seconds")));
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
+ StringPiece("Field 'dur', Invalid duration format, failed to parse "
+ "seconds")));
ow_->StartObject("")->RenderString("dur", "s")->EndObject();
CheckOutput(duration);
@@ -949,11 +947,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError3) {
EXPECT_CALL(
listener_,
- InvalidValue(_,
- StringPiece("type.googleapis.com/google.protobuf.Duration"),
- StringPiece(
- "Field 'dur', Invalid duration format, failed to "
- "parse nanos seconds")));
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
+ StringPiece("Field 'dur', Invalid duration format, failed to "
+ "parse nanos seconds")));
ow_->StartObject("")->RenderString("dur", "123.DEFs")->EndObject();
CheckOutput(duration);
@@ -1174,10 +1171,10 @@ TEST_P(ProtoStreamObjectWriterAnyTest, EmptyAnyFromEmptyObject) {
TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) {
AnyOut any;
- EXPECT_CALL(listener_,
- InvalidValue(_, StringPiece("Any"),
- StringPiece(
- "Missing or invalid @type for any field in "
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_, StringPiece("Any"),
+ StringPiece("Missing or invalid @type for any field in "
"google.protobuf.testing.anys.AnyOut")));
ow_->StartObject("")
@@ -1192,10 +1189,10 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) {
TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) {
AnyOut any;
- EXPECT_CALL(listener_,
- InvalidValue(_, StringPiece("Any"),
- StringPiece(
- "Missing or invalid @type for any field in "
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_, StringPiece("Any"),
+ StringPiece("Missing or invalid @type for any field in "
"google.protobuf.testing.anys.AnyOut")));
ow_->StartObject("")
@@ -1210,10 +1207,10 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) {
TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails3) {
AnyOut any;
- EXPECT_CALL(listener_,
- InvalidValue(_, StringPiece("Any"),
- StringPiece(
- "Missing or invalid @type for any field in "
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_, StringPiece("Any"),
+ StringPiece("Missing or invalid @type for any field in "
"google.protobuf.testing.anys.AnyOut")));
ow_->StartObject("")
@@ -1227,13 +1224,12 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails3) {
TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithInvalidTypeUrlFails) {
AnyOut any;
- EXPECT_CALL(
- listener_,
- InvalidValue(_, StringPiece("Any"),
- StringPiece(
- "Invalid type URL, type URLs must be of the form "
- "'type.googleapis.com/<typename>', got: "
- "type.other.com/some.Type")));
+ EXPECT_CALL(listener_,
+ InvalidValue(
+ _, StringPiece("Any"),
+ StringPiece("Invalid type URL, type URLs must be of the form "
+ "'type.googleapis.com/<typename>', got: "
+ "type.other.com/some.Type")));
ow_->StartObject("")
->StartObject("any")
@@ -1401,11 +1397,10 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, MaskUsingApiaryStyleShouldWork) {
TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreCloseThanOpenParentheses) {
EXPECT_CALL(
listener_,
- InvalidValue(_,
- StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
- StringPiece(
- "Field 'single_mask', Invalid FieldMask 'a(b,c))'. "
- "Cannot find matching '(' for all ')'.")));
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
+ StringPiece("Field 'single_mask', Invalid FieldMask 'a(b,c))'. "
+ "Cannot find matching '(' for all ')'.")));
ow_->StartObject("");
ow_->RenderString("id", "1");
@@ -1448,12 +1443,11 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest,
MapKeyMustBeAtTheEndOfAPathSegment) {
EXPECT_CALL(
listener_,
- InvalidValue(_,
- StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
- StringPiece(
- "Field 'single_mask', Invalid FieldMask "
- "'path.to.map[\"key1\"]a,path.to.map[\"key2\"]'. "
- "Map keys should be at the end of a path segment.")));
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
+ StringPiece("Field 'single_mask', Invalid FieldMask "
+ "'path.to.map[\"key1\"]a,path.to.map[\"key2\"]'. "
+ "Map keys should be at the end of a path segment.")));
ow_->StartObject("");
ow_->RenderString("single_mask",
@@ -1466,10 +1460,9 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustEnd) {
listener_,
InvalidValue(_,
StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
- StringPiece(
- "Field 'single_mask', Invalid FieldMask "
- "'path.to.map[\"key1\"'. Map keys should be "
- "represented as [\"some_key\"].")));
+ StringPiece("Field 'single_mask', Invalid FieldMask "
+ "'path.to.map[\"key1\"'. Map keys should be "
+ "represented as [\"some_key\"].")));
ow_->StartObject("");
ow_->RenderString("single_mask", "path.to.map[\"key1\"");
@@ -1481,10 +1474,9 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustBeEscapedCorrectly) {
listener_,
InvalidValue(_,
StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
- StringPiece(
- "Field 'single_mask', Invalid FieldMask "
- "'path.to.map[\"ke\"y1\"]'. Map keys should be "
- "represented as [\"some_key\"].")));
+ StringPiece("Field 'single_mask', Invalid FieldMask "
+ "'path.to.map[\"ke\"y1\"]'. Map keys should be "
+ "represented as [\"some_key\"].")));
ow_->StartObject("");
ow_->RenderString("single_mask", "path.to.map[\"ke\"y1\"]");
@@ -1507,6 +1499,192 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyCanContainAnyChars) {
CheckOutput(expected);
}
+class ProtoStreamObjectWriterOneOfsTest
+ : public BaseProtoStreamObjectWriterTest {
+ protected:
+ ProtoStreamObjectWriterOneOfsTest() {
+ vector<const Descriptor*> descriptors;
+ descriptors.push_back(OneOfsRequest::descriptor());
+ descriptors.push_back(google::protobuf::Struct::descriptor());
+ ResetTypeInfo(descriptors);
+ }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+ ProtoStreamObjectWriterOneOfsTest,
+ ::testing::Values(
+ testing::USE_TYPE_RESOLVER));
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForPrimitiveTypesTest) {
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(
+ _, StringPiece("oneof"),
+ StringPiece(
+ "oneof field 'data' is already set. Cannot set 'intData'")));
+
+ ow_->StartObject("");
+ ow_->RenderString("strData", "blah");
+ ow_->RenderString("intData", "123");
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForMessageTypesPrimitiveFirstTest) {
+ // Test for setting primitive oneof field first and then message field.
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'messageData'")));
+
+ // JSON: { "strData": "blah", "messageData": { "dataValue": 123 } }
+ ow_->StartObject("");
+ ow_->RenderString("strData", "blah");
+ ow_->StartObject("messageData");
+ ow_->RenderInt32("dataValue", 123);
+ ow_->EndObject();
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForMessageTypesMessageFirstTest) {
+ // Test for setting message oneof field first and then primitive field.
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'strData'")));
+
+ // JSON: { "messageData": { "dataValue": 123 }, "strData": "blah" }
+ ow_->StartObject("");
+ ow_->StartObject("messageData");
+ ow_->RenderInt32("dataValue", 123);
+ ow_->EndObject();
+ ow_->RenderString("strData", "blah");
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForStructTypesPrimitiveFirstTest) {
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'structData'")));
+
+ // JSON: { "strData": "blah", "structData": { "a": "b" } }
+ ow_->StartObject("");
+ ow_->RenderString("strData", "blah");
+ ow_->StartObject("structData");
+ ow_->RenderString("a", "b");
+ ow_->EndObject();
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForStructTypesStructFirstTest) {
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'strData'")));
+
+ // JSON: { "structData": { "a": "b" }, "strData": "blah" }
+ ow_->StartObject("");
+ ow_->StartObject("structData");
+ ow_->RenderString("a", "b");
+ ow_->EndObject();
+ ow_->RenderString("strData", "blah");
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForStructValueTypesTest) {
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'valueData'")));
+
+ // JSON: { "messageData": { "dataValue": 123 }, "valueData": { "a": "b" } }
+ ow_->StartObject("");
+ ow_->StartObject("messageData");
+ ow_->RenderInt32("dataValue", 123);
+ ow_->EndObject();
+ ow_->StartObject("valueData");
+ ow_->RenderString("a", "b");
+ ow_->EndObject();
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForWellKnownTypesPrimitiveFirstTest) {
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'tsData'")));
+
+ // JSON: { "intData": 123, "tsData": "1970-01-02T01:00:00.000Z" }
+ ow_->StartObject("");
+ ow_->RenderInt32("intData", 123);
+ ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForWellKnownTypesWktFirstTest) {
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'intData'")));
+
+ // JSON: { "tsData": "1970-01-02T01:00:00.000Z", "intData": 123 }
+ ow_->StartObject("");
+ ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
+ ow_->RenderInt32("intData", 123);
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForWellKnownTypesAndMessageTest) {
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'messageData'")));
+
+ // JSON: { "tsData": "1970-01-02T01:00:00.000Z",
+ // "messageData": { "dataValue": 123 } }
+ ow_->StartObject("");
+ ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
+ ow_->StartObject("messageData");
+ ow_->RenderInt32("dataValue", 123);
+ ow_->EndObject();
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForOneofWithinAnyTest) {
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'intData'")));
+
+ using google::protobuf::testing::oneofs::OneOfsRequest;
+ // JSON:
+ // { "anyData":
+ // { "@type":
+ // "type.googleapis.com/google.protobuf.testing.oneofs.OneOfsRequest",
+ // "strData": "blah",
+ // "intData": 123
+ // }
+ // }
+ ow_->StartObject("");
+ ow_->StartObject("anyData");
+ ow_->RenderString(
+ "@type",
+ "type.googleapis.com/google.protobuf.testing.oneofs.OneOfsRequest");
+ ow_->RenderString("strData", "blah");
+ ow_->RenderInt32("intData", 123);
+ ow_->EndObject();
+}
+
} // namespace converter
} // namespace util
} // namespace protobuf
diff --git a/src/google/protobuf/util/internal/snake2camel_objectwriter.h b/src/google/protobuf/util/internal/snake2camel_objectwriter.h
index 1a32bc56..9b4ab8a3 100644
--- a/src/google/protobuf/util/internal/snake2camel_objectwriter.h
+++ b/src/google/protobuf/util/internal/snake2camel_objectwriter.h
@@ -58,9 +58,7 @@ class Snake2CamelObjectWriter : public ObjectWriter {
// ObjectWriter methods.
virtual Snake2CamelObjectWriter* StartObject(StringPiece name) {
- ow_->StartObject(ShouldNormalizeCase(name)
- ? StringPiece(StringPiece(ToCamelCase(name)))
- : name);
+ ow_->StartObject(name);
return this;
}
@@ -70,8 +68,7 @@ class Snake2CamelObjectWriter : public ObjectWriter {
}
virtual Snake2CamelObjectWriter* StartList(StringPiece name) {
- ow_->StartList(ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name))
- : name);
+ ow_->StartList(name);
return this;
}
@@ -81,76 +78,57 @@ class Snake2CamelObjectWriter : public ObjectWriter {
}
virtual Snake2CamelObjectWriter* RenderBool(StringPiece name, bool value) {
- ow_->RenderBool(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderBool(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderInt32(StringPiece name, int32 value) {
- ow_->RenderInt32(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderInt32(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderUint32(StringPiece name,
uint32 value) {
- ow_->RenderUint32(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderUint32(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderInt64(StringPiece name, int64 value) {
- ow_->RenderInt64(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderInt64(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderUint64(StringPiece name,
uint64 value) {
- ow_->RenderUint64(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderUint64(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderDouble(StringPiece name,
double value) {
- ow_->RenderDouble(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderDouble(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderFloat(StringPiece name, float value) {
- ow_->RenderFloat(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderFloat(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderString(StringPiece name,
StringPiece value) {
- ow_->RenderString(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderString(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderBytes(StringPiece name,
StringPiece value) {
- ow_->RenderBytes(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderBytes(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderNull(StringPiece name) {
- ow_->RenderNull(ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name))
- : name);
+ ow_->RenderNull(name);
return this;
}
diff --git a/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc b/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc
index 67388c3b..e5db844c 100644
--- a/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc
@@ -47,263 +47,9 @@ class Snake2CamelObjectWriterTest : public ::testing::Test {
Snake2CamelObjectWriter testing_;
};
-TEST_F(Snake2CamelObjectWriterTest, Empty) {
- // Set expectation
- expects_.StartObject("")->EndObject();
-
- // Actual testing
- testing_.StartObject("")->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, UnderscoresOnly) {
- // Set expectation
- expects_.StartObject("")
- ->RenderInt32("", 1)
- ->RenderInt32("", 2)
- ->RenderInt32("", 3)
- ->RenderInt32("", 4)
- ->RenderInt32("", 5)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("")
- ->RenderInt32("_", 1)
- ->RenderInt32("__", 2)
- ->RenderInt32("___", 3)
- ->RenderInt32("____", 4)
- ->RenderInt32("_____", 5)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, LowercaseOnly) {
- // Set expectation
- expects_.StartObject("")
- ->RenderString("key", "value")
- ->RenderString("abracadabra", "magic")
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("")
- ->RenderString("key", "value")
- ->RenderString("abracadabra", "magic")
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, UppercaseOnly) {
- // Set expectation
- expects_.StartObject("")
- ->RenderString("key", "VALUE")
- ->RenderString("abracadabra", "MAGIC")
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("")
- ->RenderString("KEY", "VALUE")
- ->RenderString("ABRACADABRA", "MAGIC")
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, CamelCase) {
- // Set expectation
- expects_.StartObject("")
- ->RenderString("camelCase", "camelCase")
- ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog",
- "theQuickBrownFoxJumpsOverTheLazyDog")
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("")
- ->RenderString("camelCase", "camelCase")
- ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog",
- "theQuickBrownFoxJumpsOverTheLazyDog")
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, FirstCapCamelCase) {
- // Sets expectation
- expects_.StartObject("camel")
- ->RenderString("camelCase", "CamelCase")
- ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog",
- "TheQuickBrownFoxJumpsOverTheLazyDog")
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("Camel")
- ->RenderString("CamelCase", "CamelCase")
- ->RenderString("TheQuickBrownFoxJumpsOverTheLazyDog",
- "TheQuickBrownFoxJumpsOverTheLazyDog")
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, LastCapCamelCase) {
- // Sets expectation
- expects_.StartObject("lastCapCamelCasE")->EndObject();
-
- // Actual testing
- testing_.StartObject("lastCapCamelCasE")->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, MixedCapCamelCase) {
- // Sets expectation
- expects_.StartObject("googleIsTheBest")
- ->RenderFloat("iLoveGOOGLE", 1.61803f)
- ->RenderFloat("goGoogleGO", 2.71828f)
- ->RenderFloat("gBikeISCool", 3.14159f)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("GOOGLEIsTheBest")
- ->RenderFloat("ILoveGOOGLE", 1.61803f)
- ->RenderFloat("GOGoogleGO", 2.71828f)
- ->RenderFloat("GBikeISCool", 3.14159f)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, MixedCase) {
- // Sets expectation
- expects_.StartObject("snakeCaseCamelCase")
- ->RenderBool("camelCaseSnakeCase", false)
- ->RenderBool("mixedCamelAndUnderScores", false)
- ->RenderBool("goGOOGLEGo", true)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("snake_case_camelCase")
- ->RenderBool("camelCase_snake_case", false)
- ->RenderBool("MixedCamel_And_UnderScores", false)
- ->RenderBool("Go_GOOGLEGo", true)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, SnakeCase) {
- // Sets expectation
- expects_.StartObject("")
- ->RenderString("snakeCase", "snake_case")
- ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog",
- "the_quick_brown_fox_jumps_over_the_lazy_dog")
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("")
- ->RenderString("snake_case", "snake_case")
- ->RenderString("the_quick_brown_fox_jumps_over_the_lazy_dog",
- "the_quick_brown_fox_jumps_over_the_lazy_dog")
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, FirstCapSnakeCase) {
- // Sets expectation
- expects_.StartObject("firstCapSnakeCase")
- ->RenderBool("helloWorld", true)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("First_Cap_Snake_Case")
- ->RenderBool("Hello_World", true)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, AllCapSnakeCase) {
- // Sets expectation
- expects_.StartObject("allCAPSNAKECASE")
- ->RenderDouble("nyseGOOGL", 600.0L)
- ->RenderDouble("aBCDE", 1.0L)
- ->RenderDouble("klMNOP", 2.0L)
- ->RenderDouble("abcIJKPQRXYZ", 3.0L)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("ALL_CAP_SNAKE_CASE")
- ->RenderDouble("NYSE_GOOGL", 600.0L)
- ->RenderDouble("A_B_C_D_E", 1.0L)
- ->RenderDouble("KL_MN_OP", 2.0L)
- ->RenderDouble("ABC_IJK_PQR_XYZ", 3.0L)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, RepeatedUnderScoreSnakeCase) {
- // Sets expectation
- expects_.StartObject("")
- ->RenderInt32("doubleUnderscoreSnakeCase", 2)
- ->RenderInt32("tripleUnderscoreFirstCap", 3)
- ->RenderInt32("quadrupleUNDERSCOREALLCAP", 4)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("")
- ->RenderInt32("double__underscore__snake__case", 2)
- ->RenderInt32("Triple___Underscore___First___Cap", 3)
- ->RenderInt32("QUADRUPLE____UNDERSCORE____ALL____CAP", 4)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, LeadingUnderscoreSnakeCase) {
- // Sets expectation
- expects_.StartObject("leadingUnderscoreSnakeCase")
- ->RenderUint32("leadingDoubleUnderscore", 2)
- ->RenderUint32("leadingTripleUnderscoreFirstCap", 3)
- ->RenderUint32("leadingQUADRUPLEUNDERSCOREALLCAP", 4)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("_leading_underscore_snake_case")
- ->RenderUint32("__leading_double_underscore", 2)
- ->RenderUint32("___Leading_Triple_Underscore_First_Cap", 3)
- ->RenderUint32("____LEADING_QUADRUPLE_UNDERSCORE_ALL_CAP", 4)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, TrailingUnderscoreSnakeCase) {
- // Sets expectation
- expects_.StartObject("trailingUnderscoreSnakeCase")
- ->RenderInt64("trailingDoubleUnderscore", 2L)
- ->RenderInt64("trailingTripleUnderscoreFirstCap", 3L)
- ->RenderInt64("trailingQUADRUPLEUNDERSCOREALLCAP", 4L)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("trailing_underscore_snake_case")
- ->RenderInt64("trailing_double_underscore__", 2L)
- ->RenderInt64("Trailing_Triple_Underscore_First_Cap___", 3L)
- ->RenderInt64("TRAILING_QUADRUPLE_UNDERSCORE_ALL_CAP____", 4L)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, EnclosingUnderscoreSnakeCase) {
- // Sets expectation
- expects_.StartObject("enclosingUnderscoreSnakeCase")
- ->RenderUint64("enclosingDoubleUnderscore", 2L)
- ->RenderUint64("enclosingTripleUnderscoreFirstCap", 3L)
- ->RenderUint64("enclosingQUADRUPLEUNDERSCOREALLCAP", 4L)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("_enclosing_underscore_snake_case_")
- ->RenderUint64("__enclosing_double_underscore__", 2L)
- ->RenderUint64("___Enclosing_Triple_Underscore_First_Cap___", 3L)
- ->RenderUint64("____ENCLOSING_QUADRUPLE_UNDERSCORE_ALL_CAP____", 4L)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, DisableCaseNormalizationOnlyDisablesFirst) {
- // Sets expectation
- expects_.StartObject("")
- ->RenderString("snakeCase", "snake_case")
- ->RenderString(
- "the_quick_brown_fox_jumps_over_the_lazy_dog", // case retained
- "the_quick_brown_fox_jumps_over_the_lazy_dog")
- ->RenderBool("theSlowFox", true) // disable case not in effect
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("")
- ->RenderString("snake_case", "snake_case")
- ->DisableCaseNormalizationForNextKey()
- ->RenderString("the_quick_brown_fox_jumps_over_the_lazy_dog",
- "the_quick_brown_fox_jumps_over_the_lazy_dog")
- ->RenderBool("the_slow_fox", true)
- ->EndObject();
-}
+// All tests are deleted as they are no longer needed. This file will be removed
+// after the component dependecies are cleaned up.
+// TODO(skarvaje): Remove this file.
} // namespace converter
} // namespace util
diff --git a/src/google/protobuf/util/internal/testdata/default_value.proto b/src/google/protobuf/util/internal/testdata/default_value.proto
index ecfc8119..ebbdf6ab 100644
--- a/src/google/protobuf/util/internal/testdata/default_value.proto
+++ b/src/google/protobuf/util/internal/testdata/default_value.proto
@@ -43,6 +43,7 @@ message DefaultValueTestCases {
DoubleMessage repeated_double = 4;
DoubleMessage nested_message = 5;
DoubleMessage repeated_nested_message = 6;
+ DoubleMessage double_message_with_oneof = 7;
StructMessage empty_struct = 201;
StructMessage empty_struct2 = 202;
StructMessage struct_with_null_value = 203;
@@ -75,6 +76,8 @@ message DefaultValueTestCases {
MixedMap mixed1 = 404;
MixedMap2 mixed2 = 405;
MessageMap map_of_objects = 406;
+ MixedMap mixed_empty = 407;
+ MessageMap message_map_empty = 408;
DoubleValueMessage double_value = 501;
DoubleValueMessage double_value_default = 502;
}
@@ -85,6 +88,10 @@ message DoubleMessage {
DoubleMessage nested_message = 3;
repeated DoubleMessage repeated_nested_message = 4;
google.protobuf.DoubleValue double_wrapper = 100;
+ oneof value {
+ string str_value = 112;
+ int64 num_value = 113;
+ }
}
message StructMessage {
diff --git a/src/google/protobuf/util/internal/testdata/oneofs.proto b/src/google/protobuf/util/internal/testdata/oneofs.proto
new file mode 100644
index 00000000..5bc9fa08
--- /dev/null
+++ b/src/google/protobuf/util/internal/testdata/oneofs.proto
@@ -0,0 +1,68 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Proto to test oneofs.
+syntax = "proto3";
+
+import "google/protobuf/any.proto";
+import "google/protobuf/struct.proto";
+import "google/protobuf/timestamp.proto";
+
+package google.protobuf.testing.oneofs;
+option java_package = "com.google.protobuf.testing.oneofs";
+
+message OneOfsRequest {
+ string value = 1;
+ oneof data {
+ string str_data = 2;
+ int32 int_data = 3;
+ // Simple message
+ Data message_data = 4;
+ // Well known types
+ google.protobuf.Struct struct_data = 5;
+ google.protobuf.Value value_data = 6;
+ google.protobuf.ListValue list_value_data = 7;
+ google.protobuf.Timestamp ts_data = 8;
+ }
+ google.protobuf.Any any_data = 19;
+}
+
+message Data {
+ int32 data_value = 1;
+}
+
+message Response {
+ string value = 1;
+}
+
+service TestService {
+ // Test call.
+ rpc Call(OneOfsRequest) returns (Response);
+}
diff --git a/src/google/protobuf/util/internal/type_info.cc b/src/google/protobuf/util/internal/type_info.cc
index 6392e18c..a45a76e3 100644
--- a/src/google/protobuf/util/internal/type_info.cc
+++ b/src/google/protobuf/util/internal/type_info.cc
@@ -35,11 +35,11 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/type.pb.h>
+#include <google/protobuf/util/internal/utility.h>
#include <google/protobuf/stubs/stringpiece.h>
#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/status.h>
#include <google/protobuf/stubs/statusor.h>
-#include <google/protobuf/util/internal/utility.h>
namespace google {
namespace protobuf {
@@ -47,7 +47,6 @@ namespace util {
namespace converter {
namespace {
-
// A TypeInfo that looks up information provided by a TypeResolver.
class TypeInfoForTypeResolver : public TypeInfo {
public:
@@ -60,7 +59,7 @@ class TypeInfoForTypeResolver : public TypeInfo {
}
virtual util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl(
- StringPiece type_url) {
+ StringPiece type_url) const {
map<StringPiece, StatusOrType>::iterator it = cached_types_.find(type_url);
if (it != cached_types_.end()) {
return it->second;
@@ -78,12 +77,14 @@ class TypeInfoForTypeResolver : public TypeInfo {
return result;
}
- virtual const google::protobuf::Type* GetType(StringPiece type_url) {
+ virtual const google::protobuf::Type* GetTypeByTypeUrl(
+ StringPiece type_url) const {
StatusOrType result = ResolveTypeUrl(type_url);
return result.ok() ? result.ValueOrDie() : NULL;
}
- virtual const google::protobuf::Enum* GetEnum(StringPiece type_url) {
+ virtual const google::protobuf::Enum* GetEnumByTypeUrl(
+ StringPiece type_url) const {
map<StringPiece, StatusOrEnum>::iterator it = cached_enums_.find(type_url);
if (it != cached_enums_.end()) {
return it->second.ok() ? it->second.ValueOrDie() : NULL;
@@ -103,7 +104,7 @@ class TypeInfoForTypeResolver : public TypeInfo {
}
virtual const google::protobuf::Field* FindField(
- const google::protobuf::Type* type, StringPiece camel_case_name) {
+ const google::protobuf::Type* type, StringPiece camel_case_name) const {
if (indexed_types_.find(type) == indexed_types_.end()) {
PopulateNameLookupTable(type);
indexed_types_.insert(type);
@@ -131,7 +132,7 @@ class TypeInfoForTypeResolver : public TypeInfo {
}
}
- void PopulateNameLookupTable(const google::protobuf::Type* type) {
+ void PopulateNameLookupTable(const google::protobuf::Type* type) const {
for (int i = 0; i < type->fields_size(); ++i) {
const google::protobuf::Field& field = type->fields(i);
StringPiece name = field.name();
@@ -151,13 +152,13 @@ class TypeInfoForTypeResolver : public TypeInfo {
// Stores string values that will be referenced by StringPieces in
// cached_types_, cached_enums_ and camel_case_name_table_.
- set<string> string_storage_;
+ mutable set<string> string_storage_;
- map<StringPiece, StatusOrType> cached_types_;
- map<StringPiece, StatusOrEnum> cached_enums_;
+ mutable map<StringPiece, StatusOrType> cached_types_;
+ mutable map<StringPiece, StatusOrEnum> cached_enums_;
- set<const google::protobuf::Type*> indexed_types_;
- map<StringPiece, StringPiece> camel_case_name_table_;
+ mutable set<const google::protobuf::Type*> indexed_types_;
+ mutable map<StringPiece, StringPiece> camel_case_name_table_;
};
} // namespace
diff --git a/src/google/protobuf/util/internal/type_info.h b/src/google/protobuf/util/internal/type_info.h
index 67403fff..d8133176 100644
--- a/src/google/protobuf/util/internal/type_info.h
+++ b/src/google/protobuf/util/internal/type_info.h
@@ -55,24 +55,29 @@ class LIBPROTOBUF_EXPORT TypeInfo {
//
// This TypeInfo class retains the ownership of the returned pointer.
virtual util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl(
- StringPiece type_url) = 0;
+ StringPiece type_url) const = 0;
// Resolves a type url into a Type. Like ResolveTypeUrl() but returns
// NULL if the type url is invalid or the type cannot be found.
//
// This TypeInfo class retains the ownership of the returned pointer.
- virtual const google::protobuf::Type* GetType(StringPiece type_url) = 0;
+ virtual const google::protobuf::Type* GetTypeByTypeUrl(
+ StringPiece type_url) const = 0;
// Resolves a type url for an enum. Returns NULL if the type url is
// invalid or the type cannot be found.
//
// This TypeInfo class retains the ownership of the returned pointer.
- virtual const google::protobuf::Enum* GetEnum(StringPiece type_url) = 0;
+ virtual const google::protobuf::Enum* GetEnumByTypeUrl(
+ StringPiece type_url) const = 0;
// Looks up a field in the specified type given a CamelCase name.
virtual const google::protobuf::Field* FindField(
- const google::protobuf::Type* type, StringPiece camel_case_name) = 0;
+ const google::protobuf::Type* type,
+ StringPiece camel_case_name) const = 0;
+ // Creates a TypeInfo object that looks up type information from a
+ // TypeResolver. Caller takes ownership of the returned pointer.
static TypeInfo* NewTypeInfo(TypeResolver* type_resolver);
private:
diff --git a/src/google/protobuf/util/internal/type_info_test_helper.cc b/src/google/protobuf/util/internal/type_info_test_helper.cc
index 177b96e2..1b9c5154 100644
--- a/src/google/protobuf/util/internal/type_info_test_helper.cc
+++ b/src/google/protobuf/util/internal/type_info_test_helper.cc
@@ -36,6 +36,7 @@
#endif
#include <vector>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/util/internal/default_value_objectwriter.h>
@@ -89,7 +90,7 @@ TypeInfo* TypeInfoTestHelper::GetTypeInfo() { return typeinfo_.get(); }
ProtoStreamObjectSource* TypeInfoTestHelper::NewProtoSource(
io::CodedInputStream* coded_input, const string& type_url) {
- const google::protobuf::Type* type = typeinfo_->GetType(type_url);
+ const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url);
switch (type_) {
case USE_TYPE_RESOLVER: {
return new ProtoStreamObjectSource(coded_input, type_resolver_.get(),
@@ -103,7 +104,7 @@ ProtoStreamObjectSource* TypeInfoTestHelper::NewProtoSource(
ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter(
const string& type_url, strings::ByteSink* output,
ErrorListener* listener) {
- const google::protobuf::Type* type = typeinfo_->GetType(type_url);
+ const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url);
switch (type_) {
case USE_TYPE_RESOLVER: {
return new ProtoStreamObjectWriter(type_resolver_.get(), *type, output,
@@ -116,7 +117,7 @@ ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter(
DefaultValueObjectWriter* TypeInfoTestHelper::NewDefaultValueWriter(
const string& type_url, ObjectWriter* writer) {
- const google::protobuf::Type* type = typeinfo_->GetType(type_url);
+ const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url);
switch (type_) {
case USE_TYPE_RESOLVER: {
return new DefaultValueObjectWriter(type_resolver_.get(), *type, writer);
diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc
index 794777d4..5d7dcc87 100644
--- a/src/google/protobuf/util/internal/utility.cc
+++ b/src/google/protobuf/util/internal/utility.cc
@@ -30,11 +30,9 @@
#include <google/protobuf/util/internal/utility.h>
-#include <cmath>
-#include <algorithm>
-#include <utility>
-
+#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/wrappers.pb.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
@@ -301,15 +299,15 @@ bool IsMap(const google::protobuf::Field& field,
}
string DoubleAsString(double value) {
- if (value == std::numeric_limits<double>::infinity()) return "Infinity";
- if (value == -std::numeric_limits<double>::infinity()) return "-Infinity";
+ if (google::protobuf::MathLimits<double>::IsPosInf(value)) return "Infinity";
+ if (google::protobuf::MathLimits<double>::IsNegInf(value)) return "-Infinity";
if (google::protobuf::MathLimits<double>::IsNaN(value)) return "NaN";
return SimpleDtoa(value);
}
string FloatAsString(float value) {
- if (isfinite(value)) return SimpleFtoa(value);
+ if (google::protobuf::MathLimits<float>::IsFinite(value)) return SimpleFtoa(value);
return DoubleAsString(value);
}
@@ -320,8 +318,7 @@ bool SafeStrToFloat(StringPiece str, float *value) {
}
*value = static_cast<float>(double_value);
- if ((*value == numeric_limits<float>::infinity()) ||
- (*value == -numeric_limits<float>::infinity())) {
+ if (google::protobuf::MathLimits<float>::IsInf(*value)) {
return false;
}
return true;
diff --git a/src/google/protobuf/util/internal/utility.h b/src/google/protobuf/util/internal/utility.h
index d0d88c19..87f7602a 100644
--- a/src/google/protobuf/util/internal/utility.h
+++ b/src/google/protobuf/util/internal/utility.h
@@ -39,6 +39,7 @@
#include <utility>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/type.pb.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/stubs/stringpiece.h>
@@ -117,23 +118,23 @@ LIBPROTOBUF_EXPORT const string GetFullTypeWithUrl(StringPiece simple_type);
// Finds and returns option identified by name and option_name within the
// provided map. Returns NULL if none found.
-LIBPROTOBUF_EXPORT const google::protobuf::Option* FindOptionOrNull(
+const google::protobuf::Option* FindOptionOrNull(
const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
const string& option_name);
// Finds and returns the field identified by field_name in the passed tech Type
// object. Returns NULL if none found.
-LIBPROTOBUF_EXPORT const google::protobuf::Field* FindFieldInTypeOrNull(
+const google::protobuf::Field* FindFieldInTypeOrNull(
const google::protobuf::Type* type, StringPiece field_name);
// Finds and returns the EnumValue identified by enum_name in the passed tech
// Enum object. Returns NULL if none found.
-LIBPROTOBUF_EXPORT const google::protobuf::EnumValue* FindEnumValueByNameOrNull(
+const google::protobuf::EnumValue* FindEnumValueByNameOrNull(
const google::protobuf::Enum* enum_type, StringPiece enum_name);
// Finds and returns the EnumValue identified by value in the passed tech
// Enum object. Returns NULL if none found.
-LIBPROTOBUF_EXPORT const google::protobuf::EnumValue* FindEnumValueByNumberOrNull(
+const google::protobuf::EnumValue* FindEnumValueByNumberOrNull(
const google::protobuf::Enum* enum_type, int32 value);
// Converts input to camel-case and returns it.
@@ -153,7 +154,7 @@ LIBPROTOBUF_EXPORT bool IsWellKnownType(const string& type_name);
LIBPROTOBUF_EXPORT bool IsValidBoolString(const string& bool_string);
// Returns true if "field" is a protobuf map field based on its type.
-bool IsMap(const google::protobuf::Field& field,
+LIBPROTOBUF_EXPORT bool IsMap(const google::protobuf::Field& field,
const google::protobuf::Type& type);
// Infinity/NaN-aware conversion to string.
diff --git a/src/google/protobuf/util/json_util.h b/src/google/protobuf/util/json_util.h
index 6796ea08..1718bfb5 100644
--- a/src/google/protobuf/util/json_util.h
+++ b/src/google/protobuf/util/json_util.h
@@ -44,7 +44,7 @@ class ZeroCopyOutputStream;
} // namespace io
namespace util {
-struct LIBPROTOBUF_EXPORT JsonOptions {
+struct JsonOptions {
// Whether to add spaces, line breaks and indentation to make the JSON output
// easy to read.
bool add_whitespace;
@@ -65,7 +65,7 @@ struct LIBPROTOBUF_EXPORT JsonOptions {
// 2. input is not valid protobuf wire format, or conflicts with the type
// information returned by TypeResolver.
// Note that unknown fields will be discarded silently.
-LIBPROTOBUF_EXPORT util::Status BinaryToJsonStream(
+util::Status BinaryToJsonStream(
TypeResolver* resolver,
const string& type_url,
io::ZeroCopyInputStream* binary_input,
@@ -101,7 +101,7 @@ inline util::Status BinaryToJsonString(TypeResolver* resolver,
// 2. input is not valid JSON format, or conflicts with the type
// information returned by TypeResolver.
// 3. input has unknown fields.
-LIBPROTOBUF_EXPORT util::Status JsonToBinaryStream(
+util::Status JsonToBinaryStream(
TypeResolver* resolver,
const string& type_url,
io::ZeroCopyInputStream* json_input,
diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc
index 6686416c..f4dc3562 100644
--- a/src/google/protobuf/util/json_util_test.cc
+++ b/src/google/protobuf/util/json_util_test.cc
@@ -99,27 +99,28 @@ TEST_F(JsonUtilTest, TestWhitespaces) {
ToJson(m, options));
}
-TEST_F(JsonUtilTest, TestDefaultValues) {
- TestMessage m;
- JsonOptions options;
- EXPECT_EQ("{}", ToJson(m, options));
- options.always_print_primitive_fields = true;
- EXPECT_EQ(
- "{\"boolValue\":false,"
- "\"int32Value\":0,"
- "\"int64Value\":\"0\","
- "\"uint32Value\":0,"
- "\"uint64Value\":\"0\","
- "\"floatValue\":0,"
- "\"doubleValue\":0,"
- "\"stringValue\":\"\","
- "\"bytesValue\":\"\","
- // TODO(xiaofeng): The default enum value should be FOO. I believe
- // this is a bug in DefaultValueObjectWriter.
- "\"enumValue\":null"
- "}",
- ToJson(m, options));
-}
+// TODO(skarvaje): Uncomment after cl/96232915 is submitted.
+// TEST_F(JsonUtilTest, TestDefaultValues) {
+ // TestMessage m;
+ // JsonOptions options;
+ // EXPECT_EQ("{}", ToJson(m, options));
+ // options.always_print_primitive_fields = true;
+ // EXPECT_EQ(
+ // "{\"boolValue\":false,"
+ // "\"int32Value\":0,"
+ // "\"int64Value\":\"0\","
+ // "\"uint32Value\":0,"
+ // "\"uint64Value\":\"0\","
+ // "\"floatValue\":0,"
+ // "\"doubleValue\":0,"
+ // "\"stringValue\":\"\","
+ // "\"bytesValue\":\"\","
+ // // TODO(xiaofeng): The default enum value should be FOO. I believe
+ // // this is a bug in DefaultValueObjectWriter.
+ // "\"enumValue\":null"
+ // "}",
+ // ToJson(m, options));
+// }
TEST_F(JsonUtilTest, ParseMessage) {
// Some random message but good enough to verify that the parsing warpper
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
index 057b414a..d709da57 100644
--- a/src/google/protobuf/util/message_differencer.cc
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -45,6 +45,7 @@
#endif
#include <utility>
+#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/any.h>
diff --git a/src/google/protobuf/util/message_differencer_unittest.cc b/src/google/protobuf/util/message_differencer_unittest.cc
index bd19f695..701b94ae 100755
--- a/src/google/protobuf/util/message_differencer_unittest.cc
+++ b/src/google/protobuf/util/message_differencer_unittest.cc
@@ -52,6 +52,7 @@
#include <google/protobuf/map_test_util.h>
#include <google/protobuf/test_util.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/testing/googletest.h>
@@ -131,7 +132,7 @@ TEST(MessageDifferencerTest, MapFieldEqualityTest) {
unittest::TestMap msg1;
unittest::TestMap msg2;
- MapTestUtil::MapReflectionTester tester(unittest::TestMap::descriptor());
+ MapReflectionTester tester(unittest::TestMap::descriptor());
tester.SetMapFieldsViaReflection(&msg1);
tester.SetMapFieldsViaReflection(&msg2);
tester.SwapMapsViaReflection(&msg1);
diff --git a/src/google/protobuf/util/time_util.cc b/src/google/protobuf/util/time_util.cc
new file mode 100644
index 00000000..c782d691
--- /dev/null
+++ b/src/google/protobuf/util/time_util.cc
@@ -0,0 +1,525 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/time_util.h>
+
+#include <google/protobuf/stubs/time.h>
+#include <google/protobuf/stubs/int128.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/duration.pb.h>
+#include <google/protobuf/timestamp.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+using google::protobuf::Timestamp;
+using google::protobuf::Duration;
+
+namespace {
+static const int kNanosPerSecond = 1000000000;
+static const int kMicrosPerSecond = 1000000;
+static const int kMillisPerSecond = 1000;
+static const int kNanosPerMillisecond = 1000000;
+static const int kMicrosPerMillisecond = 1000;
+static const int kNanosPerMicrosecond = 1000;
+static const int kSecondsPerMinute = 60; // Note that we ignore leap seconds.
+static const int kSecondsPerHour = 3600;
+static const char kTimestampFormat[] = "%E4Y-%m-%dT%H:%M:%S";
+
+template <typename T>
+T CreateNormalized(int64 seconds, int64 nanos);
+
+template <>
+Timestamp CreateNormalized(int64 seconds, int64 nanos) {
+ // Make sure nanos is in the range.
+ if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
+ seconds += nanos / kNanosPerSecond;
+ nanos = nanos % kNanosPerSecond;
+ }
+ // For Timestamp nanos should be in the range [0, 999999999]
+ if (nanos < 0) {
+ seconds -= 1;
+ nanos += kNanosPerSecond;
+ }
+ GOOGLE_DCHECK(seconds >= TimeUtil::kTimestampMinSeconds &&
+ seconds <= TimeUtil::kTimestampMaxSeconds);
+ Timestamp result;
+ result.set_seconds(seconds);
+ result.set_nanos(static_cast<int32>(nanos));
+ return result;
+}
+
+template <>
+Duration CreateNormalized(int64 seconds, int64 nanos) {
+ // Make sure nanos is in the range.
+ if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
+ seconds += nanos / kNanosPerSecond;
+ nanos = nanos % kNanosPerSecond;
+ }
+ // nanos should have the same sign as seconds.
+ if (seconds < 0 && nanos > 0) {
+ seconds += 1;
+ nanos -= kNanosPerSecond;
+ } else if (seconds > 0 && nanos < 0) {
+ seconds -= 1;
+ nanos += kNanosPerSecond;
+ }
+ GOOGLE_DCHECK(seconds >= TimeUtil::kDurationMinSeconds &&
+ seconds <= TimeUtil::kDurationMaxSeconds);
+ Duration result;
+ result.set_seconds(seconds);
+ result.set_nanos(static_cast<int32>(nanos));
+ return result;
+}
+
+// Format nanoseconds with either 3, 6, or 9 digits depending on the required
+// precision to represent the exact value.
+string FormatNanos(int32 nanos) {
+ if (nanos % kNanosPerMillisecond == 0) {
+ return StringPrintf("%03d", nanos / kNanosPerMillisecond);
+ } else if (nanos % kNanosPerMicrosecond == 0) {
+ return StringPrintf("%06d", nanos / kNanosPerMicrosecond);
+ } else {
+ return StringPrintf("%09d", nanos);
+ }
+}
+
+string FormatTime(int64 seconds, int32 nanos) {
+ return ::google::protobuf::internal::FormatTime(seconds, nanos);
+}
+
+bool ParseTime(const string& value, int64* seconds, int32* nanos) {
+ return ::google::protobuf::internal::ParseTime(value, seconds, nanos);
+}
+
+void CurrentTime(int64* seconds, int32* nanos) {
+ return ::google::protobuf::internal::GetCurrentTime(seconds, nanos);
+}
+
+// Truncates the remainder part after division.
+int64 RoundTowardZero(int64 value, int64 divider) {
+ int64 result = value / divider;
+ int64 remainder = value % divider;
+ // Before C++11, the sign of the remainder is implementation dependent if
+ // any of the operands is negative. Here we try to enforce C++11's "rounded
+ // toward zero" semantics. For example, for (-5) / 2 an implementation may
+ // give -3 as the result with the remainder being 1. This function ensures
+ // we always return -2 (closer to zero) regardless of the implementation.
+ if (result < 0 && remainder > 0) {
+ return result + 1;
+ } else {
+ return result;
+ }
+}
+} // namespace
+
+string TimeUtil::ToString(const Timestamp& timestamp) {
+ return FormatTime(timestamp.seconds(), timestamp.nanos());
+}
+
+bool TimeUtil::FromString(const string& value, Timestamp* timestamp) {
+ int64 seconds;
+ int32 nanos;
+ if (!ParseTime(value, &seconds, &nanos)) {
+ return false;
+ }
+ *timestamp = CreateNormalized<Timestamp>(seconds, nanos);
+ return true;
+}
+
+Timestamp TimeUtil::GetCurrentTime() {
+ int64 seconds;
+ int32 nanos;
+ CurrentTime(&seconds, &nanos);
+ return CreateNormalized<Timestamp>(seconds, nanos);
+}
+
+Timestamp TimeUtil::GetEpoch() { return Timestamp(); }
+
+string TimeUtil::ToString(const Duration& duration) {
+ string result;
+ int64 seconds = duration.seconds();
+ int32 nanos = duration.nanos();
+ if (seconds < 0 || nanos < 0) {
+ result += "-";
+ seconds = -seconds;
+ nanos = -nanos;
+ }
+ result += StringPrintf("%" GOOGLE_LL_FORMAT "d", seconds);
+ if (nanos != 0) {
+ result += "." + FormatNanos(nanos);
+ }
+ result += "s";
+ return result;
+}
+
+static int64 Pow(int64 x, int y) {
+ int64 result = 1;
+ for (int i = 0; i < y; ++i) {
+ result *= x;
+ }
+ return result;
+}
+
+bool TimeUtil::FromString(const string& value, Duration* duration) {
+ if (value.length() <= 1 || value[value.length() - 1] != 's') {
+ return false;
+ }
+ bool negative = (value[0] == '-');
+ int sign_length = (negative ? 1 : 0);
+ // Parse the duration value as two integers rather than a float value
+ // to avoid precision loss.
+ string seconds_part, nanos_part;
+ size_t pos = value.find_last_of(".");
+ if (pos == string::npos) {
+ seconds_part = value.substr(sign_length, value.length() - 1 - sign_length);
+ nanos_part = "0";
+ } else {
+ seconds_part = value.substr(sign_length, pos - sign_length);
+ nanos_part = value.substr(pos + 1, value.length() - pos - 2);
+ }
+ char* end;
+ int64 seconds = strto64(seconds_part.c_str(), &end, 10);
+ if (end != seconds_part.c_str() + seconds_part.length()) {
+ return false;
+ }
+ int64 nanos = strto64(nanos_part.c_str(), &end, 10);
+ if (end != nanos_part.c_str() + nanos_part.length()) {
+ return false;
+ }
+ nanos = nanos * Pow(10, 9 - nanos_part.length());
+ if (negative) {
+ // If a Duration is negative, both seconds and nanos should be negative.
+ seconds = -seconds;
+ nanos = -nanos;
+ }
+ duration->set_seconds(seconds);
+ duration->set_nanos(static_cast<int32>(nanos));
+ return true;
+}
+
+Duration TimeUtil::NanosecondsToDuration(int64 nanos) {
+ return CreateNormalized<Duration>(nanos / kNanosPerSecond,
+ nanos % kNanosPerSecond);
+}
+
+Duration TimeUtil::MicrosecondsToDuration(int64 micros) {
+ return CreateNormalized<Duration>(
+ micros / kMicrosPerSecond,
+ (micros % kMicrosPerSecond) * kNanosPerMicrosecond);
+}
+
+Duration TimeUtil::MillisecondsToDuration(int64 millis) {
+ return CreateNormalized<Duration>(
+ millis / kMillisPerSecond,
+ (millis % kMillisPerSecond) * kNanosPerMillisecond);
+}
+
+Duration TimeUtil::SecondsToDuration(int64 seconds) {
+ return CreateNormalized<Duration>(seconds, 0);
+}
+
+Duration TimeUtil::MinutesToDuration(int64 minutes) {
+ return CreateNormalized<Duration>(minutes * kSecondsPerMinute, 0);
+}
+
+Duration TimeUtil::HoursToDuration(int64 hours) {
+ return CreateNormalized<Duration>(hours * kSecondsPerHour, 0);
+}
+
+int64 TimeUtil::DurationToNanoseconds(const Duration& duration) {
+ return duration.seconds() * kNanosPerSecond + duration.nanos();
+}
+
+int64 TimeUtil::DurationToMicroseconds(const Duration& duration) {
+ return duration.seconds() * kMicrosPerSecond +
+ RoundTowardZero(duration.nanos(), kNanosPerMicrosecond);
+}
+
+int64 TimeUtil::DurationToMilliseconds(const Duration& duration) {
+ return duration.seconds() * kMillisPerSecond +
+ RoundTowardZero(duration.nanos(), kNanosPerMillisecond);
+}
+
+int64 TimeUtil::DurationToSeconds(const Duration& duration) {
+ return duration.seconds();
+}
+
+int64 TimeUtil::DurationToMinutes(const Duration& duration) {
+ return RoundTowardZero(duration.seconds(), kSecondsPerMinute);
+}
+
+int64 TimeUtil::DurationToHours(const Duration& duration) {
+ return RoundTowardZero(duration.seconds(), kSecondsPerHour);
+}
+
+Timestamp TimeUtil::NanosecondsToTimestamp(int64 nanos) {
+ return CreateNormalized<Timestamp>(nanos / kNanosPerSecond,
+ nanos % kNanosPerSecond);
+}
+
+Timestamp TimeUtil::MicrosecondsToTimestamp(int64 micros) {
+ return CreateNormalized<Timestamp>(
+ micros / kMicrosPerSecond,
+ micros % kMicrosPerSecond * kNanosPerMicrosecond);
+}
+
+Timestamp TimeUtil::MillisecondsToTimestamp(int64 millis) {
+ return CreateNormalized<Timestamp>(
+ millis / kMillisPerSecond,
+ millis % kMillisPerSecond * kNanosPerMillisecond);
+}
+
+Timestamp TimeUtil::SecondsToTimestamp(int64 seconds) {
+ return CreateNormalized<Timestamp>(seconds, 0);
+}
+
+int64 TimeUtil::TimestampToNanoseconds(const Timestamp& timestamp) {
+ return timestamp.seconds() * kNanosPerSecond + timestamp.nanos();
+}
+
+int64 TimeUtil::TimestampToMicroseconds(const Timestamp& timestamp) {
+ return timestamp.seconds() * kMicrosPerSecond +
+ RoundTowardZero(timestamp.nanos(), kNanosPerMicrosecond);
+}
+
+int64 TimeUtil::TimestampToMilliseconds(const Timestamp& timestamp) {
+ return timestamp.seconds() * kMillisPerSecond +
+ RoundTowardZero(timestamp.nanos(), kNanosPerMillisecond);
+}
+
+int64 TimeUtil::TimestampToSeconds(const Timestamp& timestamp) {
+ return timestamp.seconds();
+}
+
+Timestamp TimeUtil::TimeTToTimestamp(time_t value) {
+ return CreateNormalized<Timestamp>(static_cast<int64>(value), 0);
+}
+
+time_t TimeUtil::TimestampToTimeT(const Timestamp& value) {
+ return static_cast<time_t>(value.seconds());
+}
+
+Timestamp TimeUtil::TimevalToTimestamp(const timeval& value) {
+ return CreateNormalized<Timestamp>(value.tv_sec,
+ value.tv_usec * kNanosPerMicrosecond);
+}
+
+timeval TimeUtil::TimestampToTimeval(const Timestamp& value) {
+ timeval result;
+ result.tv_sec = value.seconds();
+ result.tv_usec = RoundTowardZero(value.nanos(), kNanosPerMicrosecond);
+ return result;
+}
+
+Duration TimeUtil::TimevalToDuration(const timeval& value) {
+ return CreateNormalized<Duration>(value.tv_sec,
+ value.tv_usec * kNanosPerMicrosecond);
+}
+
+timeval TimeUtil::DurationToTimeval(const Duration& value) {
+ timeval result;
+ result.tv_sec = value.seconds();
+ result.tv_usec = RoundTowardZero(value.nanos(), kNanosPerMicrosecond);
+ // timeval.tv_usec's range is [0, 1000000)
+ if (result.tv_usec < 0) {
+ result.tv_sec -= 1;
+ result.tv_usec += kMicrosPerSecond;
+ }
+ return result;
+}
+
+} // namespace util
+} // namespace protobuf
+
+
+namespace protobuf {
+namespace {
+using google::protobuf::util::kNanosPerSecond;
+using google::protobuf::util::CreateNormalized;
+
+// Convert a Timestamp to uint128.
+void ToUint128(const Timestamp& value, uint128* result, bool* negative) {
+ if (value.seconds() < 0) {
+ *negative = true;
+ *result = static_cast<uint64>(-value.seconds());
+ *result = *result * kNanosPerSecond - static_cast<uint32>(value.nanos());
+ } else {
+ *negative = false;
+ *result = static_cast<uint64>(value.seconds());
+ *result = *result * kNanosPerSecond + static_cast<uint32>(value.nanos());
+ }
+}
+
+// Convert a Duration to uint128.
+void ToUint128(const Duration& value, uint128* result, bool* negative) {
+ if (value.seconds() < 0 || value.nanos() < 0) {
+ *negative = true;
+ *result = static_cast<uint64>(-value.seconds());
+ *result = *result * kNanosPerSecond + static_cast<uint32>(-value.nanos());
+ } else {
+ *negative = false;
+ *result = static_cast<uint64>(value.seconds());
+ *result = *result * kNanosPerSecond + static_cast<uint32>(value.nanos());
+ }
+}
+
+void ToTimestamp(const uint128& value, bool negative, Timestamp* timestamp) {
+ int64 seconds = static_cast<int64>(Uint128Low64(value / kNanosPerSecond));
+ int32 nanos = static_cast<int32>(Uint128Low64(value % kNanosPerSecond));
+ if (negative) {
+ seconds = -seconds;
+ nanos = -nanos;
+ if (nanos < 0) {
+ nanos += kNanosPerSecond;
+ seconds -= 1;
+ }
+ }
+ timestamp->set_seconds(seconds);
+ timestamp->set_nanos(nanos);
+}
+
+void ToDuration(const uint128& value, bool negative, Duration* duration) {
+ int64 seconds = static_cast<int64>(Uint128Low64(value / kNanosPerSecond));
+ int32 nanos = static_cast<int32>(Uint128Low64(value % kNanosPerSecond));
+ if (negative) {
+ seconds = -seconds;
+ nanos = -nanos;
+ }
+ duration->set_seconds(seconds);
+ duration->set_nanos(nanos);
+}
+} // namespace
+
+Duration& operator+=(Duration& d1, const Duration& d2) {
+ d1 = CreateNormalized<Duration>(d1.seconds() + d2.seconds(),
+ d1.nanos() + d2.nanos());
+ return d1;
+}
+
+Duration& operator-=(Duration& d1, const Duration& d2) { // NOLINT
+ d1 = CreateNormalized<Duration>(d1.seconds() - d2.seconds(),
+ d1.nanos() - d2.nanos());
+ return d1;
+}
+
+Duration& operator*=(Duration& d, int64 r) { // NOLINT
+ bool negative;
+ uint128 value;
+ ToUint128(d, &value, &negative);
+ if (r > 0) {
+ value *= static_cast<uint64>(r);
+ } else {
+ negative = !negative;
+ value *= static_cast<uint64>(-r);
+ }
+ ToDuration(value, negative, &d);
+ return d;
+}
+
+Duration& operator*=(Duration& d, double r) { // NOLINT
+ double result = (d.seconds() * 1.0 + 1.0 * d.nanos() / kNanosPerSecond) * r;
+ int64 seconds = static_cast<int64>(result);
+ int32 nanos = static_cast<int32>((result - seconds) * kNanosPerSecond);
+ // Note that we normalize here not just because nanos can have a different
+ // sign from seconds but also that nanos can be any arbitrary value when
+ // overflow happens (i.e., the result is a much larger value than what
+ // int64 can represent).
+ d = CreateNormalized<Duration>(seconds, nanos);
+ return d;
+}
+
+Duration& operator/=(Duration& d, int64 r) { // NOLINT
+ bool negative;
+ uint128 value;
+ ToUint128(d, &value, &negative);
+ if (r > 0) {
+ value /= static_cast<uint64>(r);
+ } else {
+ negative = !negative;
+ value /= static_cast<uint64>(-r);
+ }
+ ToDuration(value, negative, &d);
+ return d;
+}
+
+Duration& operator/=(Duration& d, double r) { // NOLINT
+ return d *= 1.0 / r;
+}
+
+Duration& operator%=(Duration& d1, const Duration& d2) { // NOLINT
+ bool negative1, negative2;
+ uint128 value1, value2;
+ ToUint128(d1, &value1, &negative1);
+ ToUint128(d2, &value2, &negative2);
+ uint128 result = value1 % value2;
+ // When negative values are involved in division, we round the division
+ // result towards zero. With this semantics, sign of the remainder is the
+ // same as the dividend. For example:
+ // -5 / 10 = 0, -5 % 10 = -5
+ // -5 / (-10) = 0, -5 % (-10) = -5
+ // 5 / (-10) = 0, 5 % (-10) = 5
+ ToDuration(result, negative1, &d1);
+ return d1;
+}
+
+int64 operator/(const Duration& d1, const Duration& d2) {
+ bool negative1, negative2;
+ uint128 value1, value2;
+ ToUint128(d1, &value1, &negative1);
+ ToUint128(d2, &value2, &negative2);
+ int64 result = Uint128Low64(value1 / value2);
+ if (negative1 != negative2) {
+ result = -result;
+ }
+ return result;
+}
+
+Timestamp& operator+=(Timestamp& t, const Duration& d) { // NOLINT
+ t = CreateNormalized<Timestamp>(t.seconds() + d.seconds(),
+ t.nanos() + d.nanos());
+ return t;
+}
+
+Timestamp& operator-=(Timestamp& t, const Duration& d) { // NOLINT
+ t = CreateNormalized<Timestamp>(t.seconds() - d.seconds(),
+ t.nanos() - d.nanos());
+ return t;
+}
+
+Duration operator-(const Timestamp& t1, const Timestamp& t2) {
+ return CreateNormalized<Duration>(t1.seconds() - t2.seconds(),
+ t1.nanos() - t2.nanos());
+}
+} // namespace protobuf
+
+} // namespace google
diff --git a/src/google/protobuf/util/time_util.h b/src/google/protobuf/util/time_util.h
new file mode 100644
index 00000000..58dbf8e6
--- /dev/null
+++ b/src/google/protobuf/util/time_util.h
@@ -0,0 +1,296 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__
+#define GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__
+
+#include <ctime>
+#include <ostream>
+#include <string>
+#ifdef _MSC_VER
+#include <winsock2.h>
+#else
+#include <sys/time.h>
+#endif
+
+#include <google/protobuf/duration.pb.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/timestamp.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+class LIBPROTOBUF_EXPORT TimeUtil {
+ typedef google::protobuf::Timestamp Timestamp;
+ typedef google::protobuf::Duration Duration;
+
+ public:
+ // The min/max Timestamp/Duration values we support.
+ //
+ // For "0001-01-01T00:00:00Z".
+ static const int64 kTimestampMinSeconds = -62135596800LL;
+ // For "9999-12-31T23:59:59.999999999Z".
+ static const int64 kTimestampMaxSeconds = 253402300799LL;
+ static const int64 kDurationMinSeconds = -315576000000LL;
+ static const int64 kDurationMaxSeconds = 315576000000LL;
+
+ // Converts Timestamp to/from RFC 3339 date string format.
+ // Generated output will always be Z-normalized and uses 3, 6 or 9
+ // fractional digits as required to represent the exact time. When
+ // parsing, any fractional digits (or none) and any offset are
+ // accepted as long as they fit into nano-seconds precision.
+ // Note that Timestamp can only represent time from
+ // 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. Converting
+ // a Timestamp outside of this range is undefined behavior.
+ // See https://www.ietf.org/rfc/rfc3339.txt
+ //
+ // Example of generated format:
+ // "1972-01-01T10:00:20.021Z"
+ //
+ // Example of accepted format:
+ // "1972-01-01T10:00:20.021-05:00"
+ static string ToString(const Timestamp& timestamp);
+ static bool FromString(const string& value, Timestamp* timestamp);
+
+ // Converts Duration to/from string format. The string format will contains
+ // 3, 6, or 9 fractional digits depending on the precision required to
+ // represent the exact Duration value. For example:
+ // "1s", "1.010s", "1.000000100s", "-3.100s"
+ // The range that can be represented by Duration is from -315,576,000,000
+ // to +315,576,000,000 inclusive (in seconds).
+ static string ToString(const Duration& duration);
+ static bool FromString(const string& value, Duration* timestamp);
+
+#ifdef GetCurrentTime
+#undef GetCurrentTime // Visual Studio has macro GetCurrentTime
+#endif
+ // Gets the current UTC time.
+ static Timestamp GetCurrentTime();
+ // Returns the Time representing "1970-01-01 00:00:00".
+ static Timestamp GetEpoch();
+
+ // Converts between Duration and integer types. The behavior is undefined if
+ // the input value is not in the valid range of Duration.
+ static Duration NanosecondsToDuration(int64 nanos);
+ static Duration MicrosecondsToDuration(int64 micros);
+ static Duration MillisecondsToDuration(int64 millis);
+ static Duration SecondsToDuration(int64 seconds);
+ static Duration MinutesToDuration(int64 minutes);
+ static Duration HoursToDuration(int64 hours);
+ // Result will be truncated towards zero. For example, "-1.5s" will be
+ // truncated to "-1s", and "1.5s" to "1s" when converting to seconds.
+ // It's undefined behavior if the input duration is not valid or the result
+ // exceeds the range of int64. A duration is not valid if it's not in the
+ // valid range of Duration, or have an invalid nanos value (i.e., larger
+ // than 999999999, less than -999999999, or have a different sign from the
+ // seconds part).
+ static int64 DurationToNanoseconds(const Duration& duration);
+ static int64 DurationToMicroseconds(const Duration& duration);
+ static int64 DurationToMilliseconds(const Duration& duration);
+ static int64 DurationToSeconds(const Duration& duration);
+ static int64 DurationToMinutes(const Duration& duration);
+ static int64 DurationToHours(const Duration& duration);
+ // Creates Timestamp from integer types. The integer value indicates the
+ // time elapsed from Epoch time. The behavior is undefined if the input
+ // value is not in the valid range of Timestamp.
+ static Timestamp NanosecondsToTimestamp(int64 nanos);
+ static Timestamp MicrosecondsToTimestamp(int64 micros);
+ static Timestamp MillisecondsToTimestamp(int64 millis);
+ static Timestamp SecondsToTimestamp(int64 seconds);
+ // Result will be truncated down to the nearest integer value. For example,
+ // with "1969-12-31T23:59:59.9Z", TimestampToMilliseconds() returns -100
+ // and TimestampToSeconds() returns -1. It's undefined behavior if the input
+ // Timestamp is not valid (i.e., its seconds part or nanos part does not fall
+ // in the valid range) or the return value doesn't fit into int64.
+ static int64 TimestampToNanoseconds(const Timestamp& timestamp);
+ static int64 TimestampToMicroseconds(const Timestamp& timestamp);
+ static int64 TimestampToMilliseconds(const Timestamp& timestamp);
+ static int64 TimestampToSeconds(const Timestamp& timestamp);
+
+ // Conversion to/from other time/date types. Note that these types may
+ // have a different precision and time range from Timestamp/Duration.
+ // When converting to a lower precision type, the value will be truncated
+ // to the nearest value that can be represented. If the value is
+ // out of the range of the result type, the return value is undefined.
+ //
+ // Conversion to/from time_t
+ static Timestamp TimeTToTimestamp(time_t value);
+ static time_t TimestampToTimeT(const Timestamp& value);
+
+ // Conversion to/from timeval
+ static Timestamp TimevalToTimestamp(const timeval& value);
+ static timeval TimestampToTimeval(const Timestamp& value);
+ static Duration TimevalToDuration(const timeval& value);
+ static timeval DurationToTimeval(const Duration& value);
+};
+
+} // namespace util
+} // namespace protobuf
+
+
+namespace protobuf {
+// Overloaded operators for Duration.
+//
+// Assignment operators.
+LIBPROTOBUF_EXPORT Duration& operator+=(Duration& d1, const Duration& d2); // NOLINT
+LIBPROTOBUF_EXPORT Duration& operator-=(Duration& d1, const Duration& d2); // NOLINT
+LIBPROTOBUF_EXPORT Duration& operator*=(Duration& d, int64 r); // NOLINT
+LIBPROTOBUF_EXPORT Duration& operator*=(Duration& d, double r); // NOLINT
+LIBPROTOBUF_EXPORT Duration& operator/=(Duration& d, int64 r); // NOLINT
+LIBPROTOBUF_EXPORT Duration& operator/=(Duration& d, double r); // NOLINT
+// Overload for other integer types.
+template <typename T>
+Duration& operator*=(Duration& d, T r) { // NOLINT
+ int64 x = r;
+ return d *= x;
+}
+template <typename T>
+Duration& operator/=(Duration& d, T r) { // NOLINT
+ int64 x = r;
+ return d /= x;
+}
+LIBPROTOBUF_EXPORT Duration& operator%=(Duration& d1, const Duration& d2); // NOLINT
+// Relational operators.
+inline bool operator<(const Duration& d1, const Duration& d2) {
+ if (d1.seconds() == d2.seconds()) {
+ return d1.nanos() < d2.nanos();
+ }
+ return d1.seconds() < d2.seconds();
+}
+inline bool operator>(const Duration& d1, const Duration& d2) {
+ return d2 < d1;
+}
+inline bool operator>=(const Duration& d1, const Duration& d2) {
+ return !(d1 < d2);
+}
+inline bool operator<=(const Duration& d1, const Duration& d2) {
+ return !(d2 < d1);
+}
+inline bool operator==(const Duration& d1, const Duration& d2) {
+ return d1.seconds() == d2.seconds() && d1.nanos() == d2.nanos();
+}
+inline bool operator!=(const Duration& d1, const Duration& d2) {
+ return !(d1 == d2);
+}
+// Additive operators
+inline Duration operator-(const Duration& d) {
+ Duration result;
+ result.set_seconds(-d.seconds());
+ result.set_nanos(-d.nanos());
+ return result;
+}
+inline Duration operator+(const Duration& d1, const Duration& d2) {
+ Duration result = d1;
+ return result += d2;
+}
+inline Duration operator-(const Duration& d1, const Duration& d2) {
+ Duration result = d1;
+ return result -= d2;
+}
+// Multiplicative operators
+template<typename T>
+inline Duration operator*(Duration d, T r) {
+ return d *= r;
+}
+template<typename T>
+inline Duration operator*(T r, Duration d) {
+ return d *= r;
+}
+template<typename T>
+inline Duration operator/(Duration d, T r) {
+ return d /= r;
+}
+LIBPROTOBUF_EXPORT int64 operator/(const Duration& d1, const Duration& d2);
+
+inline Duration operator%(const Duration& d1, const Duration& d2) {
+ Duration result = d1;
+ return result %= d2;
+}
+
+inline ostream& operator<<(ostream& out, const Duration& d) {
+ out << google::protobuf::util::TimeUtil::ToString(d);
+ return out;
+}
+
+// Overloaded operators for Timestamp
+//
+// Assignement operators.
+LIBPROTOBUF_EXPORT
+Timestamp& operator+=(Timestamp& t, const Duration& d); // NOLINT
+LIBPROTOBUF_EXPORT
+Timestamp& operator-=(Timestamp& t, const Duration& d); // NOLINT
+// Relational operators.
+inline bool operator<(const Timestamp& t1, const Timestamp& t2) {
+ if (t1.seconds() == t2.seconds()) {
+ return t1.nanos() < t2.nanos();
+ }
+ return t1.seconds() < t2.seconds();
+}
+inline bool operator>(const Timestamp& t1, const Timestamp& t2) {
+ return t2 < t1;
+}
+inline bool operator>=(const Timestamp& t1, const Timestamp& t2) {
+ return !(t1 < t2);
+}
+inline bool operator<=(const Timestamp& t1, const Timestamp& t2) {
+ return !(t2 < t1);
+}
+inline bool operator==(const Timestamp& t1, const Timestamp& t2) {
+ return t1.seconds() == t2.seconds() && t1.nanos() == t2.nanos();
+}
+inline bool operator!=(const Timestamp& t1, const Timestamp& t2) {
+ return !(t1 == t2);
+}
+// Additive operators.
+inline Timestamp operator+(const Timestamp& t, const Duration& d) {
+ Timestamp result = t;
+ return result += d;
+}
+inline Timestamp operator+(const Duration& d, const Timestamp& t) {
+ Timestamp result = t;
+ return result += d;
+}
+inline Timestamp operator-(const Timestamp& t, const Duration& d) {
+ Timestamp result = t;
+ return result -= d;
+}
+LIBPROTOBUF_EXPORT Duration operator-(const Timestamp& t1, const Timestamp& t2);
+
+inline ostream& operator<<(ostream& out, const Timestamp& t) {
+ out << google::protobuf::util::TimeUtil::ToString(t);
+ return out;
+}
+
+} // namespace protobuf
+
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__
diff --git a/src/google/protobuf/util/time_util_test.cc b/src/google/protobuf/util/time_util_test.cc
new file mode 100644
index 00000000..285740ab
--- /dev/null
+++ b/src/google/protobuf/util/time_util_test.cc
@@ -0,0 +1,380 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/time_util.h>
+
+#include <ctime>
+
+#include <google/protobuf/timestamp.pb.h>
+#include <google/protobuf/duration.pb.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+using google::protobuf::Timestamp;
+using google::protobuf::Duration;
+
+namespace {
+
+TEST(TimeUtilTest, TimestampStringFormat) {
+ Timestamp begin, end;
+ EXPECT_TRUE(TimeUtil::FromString("0001-01-01T00:00:00Z", &begin));
+ EXPECT_EQ(TimeUtil::kTimestampMinSeconds, begin.seconds());
+ EXPECT_EQ(0, begin.nanos());
+ EXPECT_TRUE(TimeUtil::FromString("9999-12-31T23:59:59.999999999Z", &end));
+ EXPECT_EQ(TimeUtil::kTimestampMaxSeconds, end.seconds());
+ EXPECT_EQ(999999999, end.nanos());
+ EXPECT_EQ("0001-01-01T00:00:00Z", TimeUtil::ToString(begin));
+ EXPECT_EQ("9999-12-31T23:59:59.999999999Z", TimeUtil::ToString(end));
+
+ // Test negative timestamps.
+ Timestamp time = TimeUtil::NanosecondsToTimestamp(-1);
+ EXPECT_EQ(-1, time.seconds());
+ // Timestamp's nano part is always non-negative.
+ EXPECT_EQ(999999999, time.nanos());
+ EXPECT_EQ("1969-12-31T23:59:59.999999999Z", TimeUtil::ToString(time));
+
+ // Generated output should contain 3, 6, or 9 fractional digits.
+ EXPECT_EQ("1970-01-01T00:00:00Z",
+ TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(0)));
+ EXPECT_EQ("1970-01-01T00:00:00.010Z",
+ TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(10000000)));
+ EXPECT_EQ("1970-01-01T00:00:00.000010Z",
+ TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(10000)));
+ EXPECT_EQ("1970-01-01T00:00:00.000000010Z",
+ TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(10)));
+
+ // Parsing accepts an fractional digits as long as they fit into nano
+ // precision.
+ EXPECT_TRUE(TimeUtil::FromString("1970-01-01T00:00:00.1Z", &time));
+ EXPECT_EQ(100000000, TimeUtil::TimestampToNanoseconds(time));
+ EXPECT_TRUE(TimeUtil::FromString("1970-01-01T00:00:00.0001Z", &time));
+ EXPECT_EQ(100000, TimeUtil::TimestampToNanoseconds(time));
+ EXPECT_TRUE(TimeUtil::FromString("1970-01-01T00:00:00.0000001Z", &time));
+ EXPECT_EQ(100, TimeUtil::TimestampToNanoseconds(time));
+
+ // Also accpets offsets.
+ EXPECT_TRUE(TimeUtil::FromString("1970-01-01T00:00:00-08:00", &time));
+ EXPECT_EQ(8 * 3600, TimeUtil::TimestampToSeconds(time));
+}
+
+TEST(TimeUtilTest, DurationStringFormat) {
+ Timestamp begin, end;
+ EXPECT_TRUE(TimeUtil::FromString("0001-01-01T00:00:00Z", &begin));
+ EXPECT_TRUE(TimeUtil::FromString("9999-12-31T23:59:59.999999999Z", &end));
+
+ EXPECT_EQ("315537897599.999999999s", TimeUtil::ToString(end - begin));
+ EXPECT_EQ(999999999, (end - begin).nanos());
+ EXPECT_EQ("-315537897599.999999999s", TimeUtil::ToString(begin - end));
+ EXPECT_EQ(-999999999, (begin - end).nanos());
+
+ // Generated output should contain 3, 6, or 9 fractional digits.
+ EXPECT_EQ("1s", TimeUtil::ToString(TimeUtil::SecondsToDuration(1)));
+ EXPECT_EQ("0.010s", TimeUtil::ToString(TimeUtil::MillisecondsToDuration(10)));
+ EXPECT_EQ("0.000010s",
+ TimeUtil::ToString(TimeUtil::MicrosecondsToDuration(10)));
+ EXPECT_EQ("0.000000010s",
+ TimeUtil::ToString(TimeUtil::NanosecondsToDuration(10)));
+
+ // Parsing accepts an fractional digits as long as they fit into nano
+ // precision.
+ Duration d;
+ EXPECT_TRUE(TimeUtil::FromString("0.1s", &d));
+ EXPECT_EQ(100, TimeUtil::DurationToMilliseconds(d));
+ EXPECT_TRUE(TimeUtil::FromString("0.0001s", &d));
+ EXPECT_EQ(100, TimeUtil::DurationToMicroseconds(d));
+ EXPECT_TRUE(TimeUtil::FromString("0.0000001s", &d));
+ EXPECT_EQ(100, TimeUtil::DurationToNanoseconds(d));
+
+ // Duration must support range from -315,576,000,000s to +315576000000s
+ // which includes negative values.
+ EXPECT_TRUE(TimeUtil::FromString("315576000000.999999999s", &d));
+ EXPECT_EQ(315576000000LL, d.seconds());
+ EXPECT_EQ(999999999, d.nanos());
+ EXPECT_TRUE(TimeUtil::FromString("-315576000000.999999999s", &d));
+ EXPECT_EQ(-315576000000LL, d.seconds());
+ EXPECT_EQ(-999999999, d.nanos());
+}
+
+TEST(TimeUtilTest, GetEpoch) {
+ EXPECT_EQ(0, TimeUtil::TimestampToNanoseconds(TimeUtil::GetEpoch()));
+}
+
+TEST(TimeUtilTest, DurationIntegerConversion) {
+ EXPECT_EQ("0.000000001s",
+ TimeUtil::ToString(TimeUtil::NanosecondsToDuration(1)));
+ EXPECT_EQ("-0.000000001s",
+ TimeUtil::ToString(TimeUtil::NanosecondsToDuration(-1)));
+ EXPECT_EQ("0.000001s",
+ TimeUtil::ToString(TimeUtil::MicrosecondsToDuration(1)));
+ EXPECT_EQ("-0.000001s",
+ TimeUtil::ToString(TimeUtil::MicrosecondsToDuration(-1)));
+ EXPECT_EQ("0.001s", TimeUtil::ToString(TimeUtil::MillisecondsToDuration(1)));
+ EXPECT_EQ("-0.001s",
+ TimeUtil::ToString(TimeUtil::MillisecondsToDuration(-1)));
+ EXPECT_EQ("1s", TimeUtil::ToString(TimeUtil::SecondsToDuration(1)));
+ EXPECT_EQ("-1s", TimeUtil::ToString(TimeUtil::SecondsToDuration(-1)));
+ EXPECT_EQ("60s", TimeUtil::ToString(TimeUtil::MinutesToDuration(1)));
+ EXPECT_EQ("-60s", TimeUtil::ToString(TimeUtil::MinutesToDuration(-1)));
+ EXPECT_EQ("3600s", TimeUtil::ToString(TimeUtil::HoursToDuration(1)));
+ EXPECT_EQ("-3600s", TimeUtil::ToString(TimeUtil::HoursToDuration(-1)));
+
+ EXPECT_EQ(
+ 1, TimeUtil::DurationToNanoseconds(TimeUtil::NanosecondsToDuration(1)));
+ EXPECT_EQ(
+ -1, TimeUtil::DurationToNanoseconds(TimeUtil::NanosecondsToDuration(-1)));
+ EXPECT_EQ(
+ 1, TimeUtil::DurationToMicroseconds(TimeUtil::MicrosecondsToDuration(1)));
+ EXPECT_EQ(-1, TimeUtil::DurationToMicroseconds(
+ TimeUtil::MicrosecondsToDuration(-1)));
+ EXPECT_EQ(
+ 1, TimeUtil::DurationToMilliseconds(TimeUtil::MillisecondsToDuration(1)));
+ EXPECT_EQ(-1, TimeUtil::DurationToMilliseconds(
+ TimeUtil::MillisecondsToDuration(-1)));
+ EXPECT_EQ(1, TimeUtil::DurationToSeconds(TimeUtil::SecondsToDuration(1)));
+ EXPECT_EQ(-1, TimeUtil::DurationToSeconds(TimeUtil::SecondsToDuration(-1)));
+ EXPECT_EQ(1, TimeUtil::DurationToMinutes(TimeUtil::MinutesToDuration(1)));
+ EXPECT_EQ(-1, TimeUtil::DurationToMinutes(TimeUtil::MinutesToDuration(-1)));
+ EXPECT_EQ(1, TimeUtil::DurationToHours(TimeUtil::HoursToDuration(1)));
+ EXPECT_EQ(-1, TimeUtil::DurationToHours(TimeUtil::HoursToDuration(-1)));
+
+ // Test truncation behavior.
+ EXPECT_EQ(1, TimeUtil::DurationToMicroseconds(
+ TimeUtil::NanosecondsToDuration(1999)));
+ // For negative values, Duration will be rounded towards 0.
+ EXPECT_EQ(-1, TimeUtil::DurationToMicroseconds(
+ TimeUtil::NanosecondsToDuration(-1999)));
+}
+
+TEST(TestUtilTest, TimestampIntegerConversion) {
+ EXPECT_EQ("1970-01-01T00:00:00.000000001Z",
+ TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(1)));
+ EXPECT_EQ("1969-12-31T23:59:59.999999999Z",
+ TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(-1)));
+ EXPECT_EQ("1970-01-01T00:00:00.000001Z",
+ TimeUtil::ToString(TimeUtil::MicrosecondsToTimestamp(1)));
+ EXPECT_EQ("1969-12-31T23:59:59.999999Z",
+ TimeUtil::ToString(TimeUtil::MicrosecondsToTimestamp(-1)));
+ EXPECT_EQ("1970-01-01T00:00:00.001Z",
+ TimeUtil::ToString(TimeUtil::MillisecondsToTimestamp(1)));
+ EXPECT_EQ("1969-12-31T23:59:59.999Z",
+ TimeUtil::ToString(TimeUtil::MillisecondsToTimestamp(-1)));
+ EXPECT_EQ("1970-01-01T00:00:01Z",
+ TimeUtil::ToString(TimeUtil::SecondsToTimestamp(1)));
+ EXPECT_EQ("1969-12-31T23:59:59Z",
+ TimeUtil::ToString(TimeUtil::SecondsToTimestamp(-1)));
+
+ EXPECT_EQ(
+ 1, TimeUtil::TimestampToNanoseconds(TimeUtil::NanosecondsToTimestamp(1)));
+ EXPECT_EQ(-1, TimeUtil::TimestampToNanoseconds(
+ TimeUtil::NanosecondsToTimestamp(-1)));
+ EXPECT_EQ(1, TimeUtil::TimestampToMicroseconds(
+ TimeUtil::MicrosecondsToTimestamp(1)));
+ EXPECT_EQ(-1, TimeUtil::TimestampToMicroseconds(
+ TimeUtil::MicrosecondsToTimestamp(-1)));
+ EXPECT_EQ(1, TimeUtil::TimestampToMilliseconds(
+ TimeUtil::MillisecondsToTimestamp(1)));
+ EXPECT_EQ(-1, TimeUtil::TimestampToMilliseconds(
+ TimeUtil::MillisecondsToTimestamp(-1)));
+ EXPECT_EQ(1, TimeUtil::TimestampToSeconds(TimeUtil::SecondsToTimestamp(1)));
+ EXPECT_EQ(-1, TimeUtil::TimestampToSeconds(TimeUtil::SecondsToTimestamp(-1)));
+
+ // Test truncation behavior.
+ EXPECT_EQ(1, TimeUtil::TimestampToMicroseconds(
+ TimeUtil::NanosecondsToTimestamp(1999)));
+ // For negative values, Timestamp will be rounded down.
+ // For example, "1969-12-31T23:59:59.5Z" (i.e., -0.5s) rounded to seconds
+ // will be "1969-12-31T23:59:59Z" (i.e., -1s) rather than
+ // "1970-01-01T00:00:00Z" (i.e., 0s).
+ EXPECT_EQ(-2, TimeUtil::TimestampToMicroseconds(
+ TimeUtil::NanosecondsToTimestamp(-1999)));
+}
+
+TEST(TimeUtilTest, TimeTConversion) {
+ time_t value = time(NULL);
+ EXPECT_EQ(value,
+ TimeUtil::TimestampToTimeT(TimeUtil::TimeTToTimestamp(value)));
+ EXPECT_EQ(
+ 1, TimeUtil::TimestampToTimeT(TimeUtil::MillisecondsToTimestamp(1999)));
+}
+
+TEST(TimeUtilTest, TimevalConversion) {
+ timeval value = TimeUtil::TimestampToTimeval(
+ TimeUtil::NanosecondsToTimestamp(1999999999));
+ EXPECT_EQ(1, value.tv_sec);
+ EXPECT_EQ(999999, value.tv_usec);
+ value = TimeUtil::TimestampToTimeval(
+ TimeUtil::NanosecondsToTimestamp(-1999999999));
+ EXPECT_EQ(-2, value.tv_sec);
+ EXPECT_EQ(0, value.tv_usec);
+
+ value =
+ TimeUtil::DurationToTimeval(TimeUtil::NanosecondsToDuration(1999999999));
+ EXPECT_EQ(1, value.tv_sec);
+ EXPECT_EQ(999999, value.tv_usec);
+ value =
+ TimeUtil::DurationToTimeval(TimeUtil::NanosecondsToDuration(-1999999999));
+ EXPECT_EQ(-2, value.tv_sec);
+ EXPECT_EQ(1, value.tv_usec);
+}
+
+TEST(TimeUtilTest, DurationOperators) {
+ Duration one_second = TimeUtil::SecondsToDuration(1);
+ Duration one_nano = TimeUtil::NanosecondsToDuration(1);
+
+ // Test +/-
+ Duration a = one_second;
+ a += one_second;
+ a -= one_nano;
+ EXPECT_EQ("1.999999999s", TimeUtil::ToString(a));
+ Duration b = -a;
+ EXPECT_EQ("-1.999999999s", TimeUtil::ToString(b));
+ EXPECT_EQ("3.999999998s", TimeUtil::ToString(a + a));
+ EXPECT_EQ("0s", TimeUtil::ToString(a + b));
+ EXPECT_EQ("0s", TimeUtil::ToString(b + a));
+ EXPECT_EQ("-3.999999998s", TimeUtil::ToString(b + b));
+ EXPECT_EQ("3.999999998s", TimeUtil::ToString(a - b));
+ EXPECT_EQ("0s", TimeUtil::ToString(a - a));
+ EXPECT_EQ("0s", TimeUtil::ToString(b - b));
+ EXPECT_EQ("-3.999999998s", TimeUtil::ToString(b - a));
+
+ // Test *
+ EXPECT_EQ(a + a, a * 2);
+ EXPECT_EQ(b + b, a * (-2));
+ EXPECT_EQ(b + b, b * 2);
+ EXPECT_EQ(a + a, b * (-2));
+ EXPECT_EQ("0.999999999s", TimeUtil::ToString(a * 0.5));
+ EXPECT_EQ("-0.999999999s", TimeUtil::ToString(b * 0.5));
+ // Multiplication should not overflow if the result fits into the supported
+ // range of Duration (intermediate result may be larger than int64).
+ EXPECT_EQ("315575999684.424s",
+ TimeUtil::ToString((one_second - one_nano) * 315576000000LL));
+ EXPECT_EQ("-315575999684.424s",
+ TimeUtil::ToString((one_nano - one_second) * 315576000000LL));
+ EXPECT_EQ("-315575999684.424s",
+ TimeUtil::ToString((one_second - one_nano) * (-315576000000LL)));
+
+ // Test / and %
+ EXPECT_EQ("0.999999999s", TimeUtil::ToString(a / 2));
+ EXPECT_EQ("-0.999999999s", TimeUtil::ToString(b / 2));
+ Duration large = TimeUtil::SecondsToDuration(315576000000LL) - one_nano;
+ // We have to handle division with values beyond 64 bits.
+ EXPECT_EQ("0.999999999s", TimeUtil::ToString(large / 315576000000LL));
+ EXPECT_EQ("-0.999999999s", TimeUtil::ToString((-large) / 315576000000LL));
+ EXPECT_EQ("-0.999999999s", TimeUtil::ToString(large / (-315576000000LL)));
+ Duration large2 = large + one_nano;
+ EXPECT_EQ(large, large % large2);
+ EXPECT_EQ(-large, (-large) % large2);
+ EXPECT_EQ(large, large % (-large2));
+ EXPECT_EQ(one_nano, large2 % large);
+ EXPECT_EQ(-one_nano, (-large2) % large);
+ EXPECT_EQ(one_nano, large2 % (-large));
+ // Some corner cases about negative values.
+ //
+ // (-5) / 2 = -2, remainder = -1
+ // (-5) / (-2) = 2, remainder = -1
+ a = TimeUtil::NanosecondsToDuration(-5);
+ EXPECT_EQ(TimeUtil::NanosecondsToDuration(-2), a / 2);
+ EXPECT_EQ(TimeUtil::NanosecondsToDuration(2), a / (-2));
+ b = TimeUtil::NanosecondsToDuration(2);
+ EXPECT_EQ(-2, a / b);
+ EXPECT_EQ(TimeUtil::NanosecondsToDuration(-1), a % b);
+ EXPECT_EQ(2, a / (-b));
+ EXPECT_EQ(TimeUtil::NanosecondsToDuration(-1), a % (-b));
+
+ // Test relational operators.
+ EXPECT_TRUE(one_nano < one_second);
+ EXPECT_FALSE(one_second < one_second);
+ EXPECT_FALSE(one_second < one_nano);
+ EXPECT_FALSE(-one_nano < -one_second);
+ EXPECT_FALSE(-one_second < -one_second);
+ EXPECT_TRUE(-one_second < -one_nano);
+ EXPECT_TRUE(-one_nano < one_nano);
+ EXPECT_FALSE(one_nano < -one_nano);
+
+ EXPECT_FALSE(one_nano > one_second);
+ EXPECT_FALSE(one_nano > one_nano);
+ EXPECT_TRUE(one_second > one_nano);
+
+ EXPECT_FALSE(one_nano >= one_second);
+ EXPECT_TRUE(one_nano >= one_nano);
+ EXPECT_TRUE(one_second >= one_nano);
+
+ EXPECT_TRUE(one_nano <= one_second);
+ EXPECT_TRUE(one_nano <= one_nano);
+ EXPECT_FALSE(one_second <= one_nano);
+
+ EXPECT_TRUE(one_nano == one_nano);
+ EXPECT_FALSE(one_nano == one_second);
+
+ EXPECT_FALSE(one_nano != one_nano);
+ EXPECT_TRUE(one_nano != one_second);
+}
+
+TEST(TimeUtilTest, TimestampOperators) {
+ Timestamp begin, end;
+ EXPECT_TRUE(TimeUtil::FromString("0001-01-01T00:00:00Z", &begin));
+ EXPECT_TRUE(TimeUtil::FromString("9999-12-31T23:59:59.999999999Z", &end));
+ Duration d = end - begin;
+ EXPECT_TRUE(end == begin + d);
+ EXPECT_TRUE(end == d + begin);
+ EXPECT_TRUE(begin == end - d);
+
+ // Test relational operators
+ Timestamp t1 = begin + d / 4;
+ Timestamp t2 = end - d / 4;
+ EXPECT_TRUE(t1 < t2);
+ EXPECT_FALSE(t1 < t1);
+ EXPECT_FALSE(t2 < t1);
+ EXPECT_FALSE(t1 > t2);
+ EXPECT_FALSE(t1 > t1);
+ EXPECT_TRUE(t2 > t1);
+ EXPECT_FALSE(t1 >= t2);
+ EXPECT_TRUE(t1 >= t1);
+ EXPECT_TRUE(t2 >= t1);
+ EXPECT_TRUE(t1 <= t2);
+ EXPECT_TRUE(t1 <= t1);
+ EXPECT_FALSE(t2 <= t1);
+
+ EXPECT_FALSE(t1 == t2);
+ EXPECT_TRUE(t1 == t1);
+ EXPECT_FALSE(t2 == t1);
+ EXPECT_TRUE(t1 != t2);
+ EXPECT_FALSE(t1 != t1);
+ EXPECT_TRUE(t2 != t1);
+}
+
+} // namespace
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/type_resolver_util.cc b/src/google/protobuf/util/type_resolver_util.cc
index 053a4ed7..908634eb 100644
--- a/src/google/protobuf/util/type_resolver_util.cc
+++ b/src/google/protobuf/util/type_resolver_util.cc
@@ -35,6 +35,7 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/status.h>
namespace google {
@@ -64,6 +65,47 @@ bool SplitTypeUrl(const string& type_url,
return true;
}
+// This code is originally defined in
+// //google/protobuf/util/converter/utility.h. Copied here due to component
+// dependency.
+// TODO(xiaofeng): Remove this when converter code is in components.
+string ToCamelCase(const StringPiece input) {
+ bool capitalize_next = false;
+ bool was_cap = true;
+ bool is_cap = false;
+ bool first_word = true;
+ string result;
+ result.reserve(input.size());
+
+ for (size_t i = 0; i < input.size(); ++i, was_cap = is_cap) {
+ is_cap = ascii_isupper(input[i]);
+ if (input[i] == '_') {
+ capitalize_next = true;
+ if (!result.empty()) first_word = false;
+ continue;
+ } else if (first_word) {
+ // Consider when the current character B is capitalized,
+ // first word ends when:
+ // 1) following a lowercase: "...aB..."
+ // 2) followed by a lowercase: "...ABc..."
+ if (!result.empty() && is_cap &&
+ (!was_cap || (i + 1 < input.size() && ascii_islower(input[i + 1])))) {
+ first_word = false;
+ } else {
+ result.push_back(ascii_tolower(input[i]));
+ continue;
+ }
+ } else if (capitalize_next) {
+ capitalize_next = false;
+ if (ascii_islower(input[i])) {
+ result.push_back(ascii_toupper(input[i]));
+ continue;
+ }
+ }
+ result.push_back(input[i]);
+ }
+ return result;
+}
class DescriptorPoolTypeResolver : public TypeResolver {
public:
@@ -155,6 +197,7 @@ class DescriptorPoolTypeResolver : public TypeResolver {
}
field->set_number(descriptor->number());
field->set_name(descriptor->name());
+ field->set_json_name(ToCamelCase(descriptor->name()));
if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE) {
field->set_type_url(GetTypeUrl(descriptor->message_type()));
} else if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index c5db963b..5ee4e25d 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/descriptor.h>
@@ -460,6 +461,10 @@ bool WireFormat::ParseAndMergeMessageSetField(uint32 field_number,
}
}
+static bool StrictUtf8Check(const FieldDescriptor* field) {
+ return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
bool WireFormat::ParseAndMergeField(
uint32 tag,
const FieldDescriptor* field, // May be NULL for unknown
@@ -632,10 +637,19 @@ bool WireFormat::ParseAndMergeField(
// Handle strings separately so that we can optimize the ctype=CORD case.
case FieldDescriptor::TYPE_STRING: {
+ bool strict_utf8_check = StrictUtf8Check(field);
string value;
if (!WireFormatLite::ReadString(input, &value)) return false;
- VerifyUTF8StringNamedField(value.data(), value.length(), PARSE,
- field->name().c_str());
+ if (strict_utf8_check) {
+ if (!WireFormatLite::VerifyUtf8String(
+ value.data(), value.length(), WireFormatLite::PARSE,
+ field->full_name().c_str())) {
+ return false;
+ }
+ } else {
+ VerifyUTF8StringNamedField(value.data(), value.length(), PARSE,
+ field->full_name().c_str());
+ }
if (field->is_repeated()) {
message_reflection->AddString(message, field, value);
} else {
@@ -893,13 +907,20 @@ void WireFormat::SerializeFieldWithCachedSizes(
// Handle strings separately so that we can get string references
// instead of copying.
case FieldDescriptor::TYPE_STRING: {
+ bool strict_utf8_check = StrictUtf8Check(field);
string scratch;
const string& value = field->is_repeated() ?
message_reflection->GetRepeatedStringReference(
message, field, j, &scratch) :
message_reflection->GetStringReference(message, field, &scratch);
- VerifyUTF8StringNamedField(value.data(), value.length(), SERIALIZE,
- field->name().c_str());
+ if (strict_utf8_check) {
+ WireFormatLite::VerifyUtf8String(value.data(), value.length(),
+ WireFormatLite::SERIALIZE,
+ field->full_name().c_str());
+ } else {
+ VerifyUTF8StringNamedField(value.data(), value.length(), SERIALIZE,
+ field->full_name().c_str());
+ }
WireFormatLite::WriteString(field->number(), value, output);
break;
}
@@ -1107,34 +1128,6 @@ int WireFormat::MessageSetItemByteSize(
return our_size;
}
-void WireFormat::VerifyUTF8StringFallback(const char* data,
- int size,
- Operation op,
- const char* field_name) {
- if (!IsStructurallyValidUTF8(data, size)) {
- const char* operation_str = NULL;
- switch (op) {
- case PARSE:
- operation_str = "parsing";
- break;
- case SERIALIZE:
- operation_str = "serializing";
- break;
- // no default case: have the compiler warn if a case is not covered.
- }
- string quoted_field_name = "";
- if (field_name != NULL) {
- quoted_field_name = StringPrintf(" '%s'", field_name);
- }
- // no space below to avoid double space when the field name is missing.
- GOOGLE_LOG(ERROR) << "String field" << quoted_field_name << " contains invalid "
- << "UTF-8 data when " << operation_str << " a protocol "
- << "buffer. Use the 'bytes' type if you intend to send raw "
- << "bytes. ";
- }
-}
-
-
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h
index 84270fee..941be75b 100644
--- a/src/google/protobuf/wire_format.h
+++ b/src/google/protobuf/wire_format.h
@@ -231,8 +231,8 @@ class LIBPROTOBUF_EXPORT WireFormat {
const Message& message);
enum Operation {
- PARSE,
- SERIALIZE,
+ PARSE = 0,
+ SERIALIZE = 1,
};
// Verifies that a string field is valid UTF8, logging an error if not.
@@ -247,13 +247,6 @@ class LIBPROTOBUF_EXPORT WireFormat {
const char* field_name);
private:
- // Verifies that a string field is valid UTF8, logging an error if not.
- static void VerifyUTF8StringFallback(
- const char* data,
- int size,
- Operation op,
- const char* field_name);
-
// Skip a MessageSet field.
static bool SkipMessageSetField(io::CodedInputStream* input,
uint32 field_number,
@@ -265,8 +258,6 @@ class LIBPROTOBUF_EXPORT WireFormat {
Message* message,
io::CodedInputStream* input);
-
-
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormat);
};
@@ -321,7 +312,8 @@ inline int WireFormat::TagSize(int field_number, FieldDescriptor::Type type) {
inline void WireFormat::VerifyUTF8String(const char* data, int size,
WireFormat::Operation op) {
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
- WireFormat::VerifyUTF8StringFallback(data, size, op, NULL);
+ WireFormatLite::VerifyUtf8String(
+ data, size, static_cast<WireFormatLite::Operation>(op), NULL);
#else
// Avoid the compiler warning about unsued variables.
(void)data; (void)size; (void)op;
@@ -332,7 +324,8 @@ inline void WireFormat::VerifyUTF8StringNamedField(
const char* data, int size, WireFormat::Operation op,
const char* field_name) {
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
- WireFormat::VerifyUTF8StringFallback(data, size, op, field_name);
+ WireFormatLite::VerifyUtf8String(
+ data, size, static_cast<WireFormatLite::Operation>(op), field_name);
#endif
}
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index 2ce4920c..847e3500 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -37,11 +37,14 @@
#include <stack>
#include <string>
#include <vector>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/io/coded_stream_inl.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+
namespace google {
namespace protobuf {
namespace internal {
@@ -484,9 +487,9 @@ void WireFormatLite::WriteMessageMaybeToArray(int field_number,
}
}
-static inline bool ReadBytesToString(io::CodedInputStream* input,
- string* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
-static inline bool ReadBytesToString(io::CodedInputStream* input,
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE static bool ReadBytesToString(
+ io::CodedInputStream* input, string* value);
+inline static bool ReadBytesToString(io::CodedInputStream* input,
string* value) {
uint32 length;
return input->ReadVarint32(&length) &&
@@ -504,6 +507,35 @@ bool WireFormatLite::ReadBytes(io::CodedInputStream* input, string** p) {
return ReadBytesToString(input, *p);
}
+bool WireFormatLite::VerifyUtf8String(const char* data,
+ int size,
+ Operation op,
+ const char* field_name) {
+ if (!IsStructurallyValidUTF8(data, size)) {
+ const char* operation_str = NULL;
+ switch (op) {
+ case PARSE:
+ operation_str = "parsing";
+ break;
+ case SERIALIZE:
+ operation_str = "serializing";
+ break;
+ // no default case: have the compiler warn if a case is not covered.
+ }
+ string quoted_field_name = "";
+ if (field_name != NULL) {
+ quoted_field_name = StringPrintf(" '%s'", field_name);
+ }
+ // no space below to avoid double space when the field name is missing.
+ GOOGLE_LOG(ERROR) << "String field" << quoted_field_name << " contains invalid "
+ << "UTF-8 data when " << operation_str << " a protocol "
+ << "buffer. Use the 'bytes' type if you intend to send raw "
+ << "bytes. ";
+ return false;
+ }
+ return true;
+}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h
index ac83abdc..55fc7ecd 100644
--- a/src/google/protobuf/wire_format_lite.h
+++ b/src/google/protobuf/wire_format_lite.h
@@ -250,17 +250,17 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
// For primitive fields, we just use a templatized routine parameterized by
// the represented type and the FieldType. These are specialized with the
// appropriate definition for each declared type.
- template <typename CType, enum FieldType DeclaredType>
- static inline bool ReadPrimitive(input, CType* value) INL;
+ template <typename CType, enum FieldType DeclaredType> INL
+ static bool ReadPrimitive(input, CType* value);
// Reads repeated primitive values, with optimizations for repeats.
// tag_size and tag should both be compile-time constants provided by the
// protocol compiler.
- template <typename CType, enum FieldType DeclaredType>
- static inline bool ReadRepeatedPrimitive(int tag_size,
- uint32 tag,
- input,
- RepeatedField<CType>* value) INL;
+ template <typename CType, enum FieldType DeclaredType> INL
+ static bool ReadRepeatedPrimitive(int tag_size,
+ uint32 tag,
+ input,
+ RepeatedField<CType>* value);
// Identical to ReadRepeatedPrimitive, except will not inline the
// implementation.
@@ -275,16 +275,14 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
//
// This is only implemented for the types with fixed wire size, e.g.
// float, double, and the (s)fixed* types.
- template <typename CType, enum FieldType DeclaredType>
- static inline const uint8* ReadPrimitiveFromArray(const uint8* buffer,
- CType* value) INL;
+ template <typename CType, enum FieldType DeclaredType> INL
+ static const uint8* ReadPrimitiveFromArray(const uint8* buffer, CType* value);
// Reads a primitive packed field.
//
// This is only implemented for packable types.
- template <typename CType, enum FieldType DeclaredType>
- static inline bool ReadPackedPrimitive(input,
- RepeatedField<CType>* value) INL;
+ template <typename CType, enum FieldType DeclaredType> INL
+ static bool ReadPackedPrimitive(input, RepeatedField<CType>* value);
// Identical to ReadPackedPrimitive, except will not inline the
// implementation.
@@ -318,6 +316,16 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
static bool ReadBytes(input, string** p);
+ enum Operation {
+ PARSE = 0,
+ SERIALIZE = 1,
+ };
+
+ // Returns true if the data is valid UTF-8.
+ static bool VerifyUtf8String(const char* data, int size,
+ Operation op,
+ const char* field_name);
+
static inline bool ReadGroup (field_number, input, MessageLite* value);
static inline bool ReadMessage(input, MessageLite* value);
@@ -344,23 +352,23 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
// Write a tag. The Write*() functions typically include the tag, so
// normally there's no need to call this unless using the Write*NoTag()
// variants.
- static inline void WriteTag(field_number, WireType type, output) INL;
+ INL static void WriteTag(field_number, WireType type, output);
// Write fields, without tags.
- static inline void WriteInt32NoTag (int32 value, output) INL;
- static inline void WriteInt64NoTag (int64 value, output) INL;
- static inline void WriteUInt32NoTag (uint32 value, output) INL;
- static inline void WriteUInt64NoTag (uint64 value, output) INL;
- static inline void WriteSInt32NoTag (int32 value, output) INL;
- static inline void WriteSInt64NoTag (int64 value, output) INL;
- static inline void WriteFixed32NoTag (uint32 value, output) INL;
- static inline void WriteFixed64NoTag (uint64 value, output) INL;
- static inline void WriteSFixed32NoTag(int32 value, output) INL;
- static inline void WriteSFixed64NoTag(int64 value, output) INL;
- static inline void WriteFloatNoTag (float value, output) INL;
- static inline void WriteDoubleNoTag (double value, output) INL;
- static inline void WriteBoolNoTag (bool value, output) INL;
- static inline void WriteEnumNoTag (int value, output) INL;
+ INL static void WriteInt32NoTag (int32 value, output);
+ INL static void WriteInt64NoTag (int64 value, output);
+ INL static void WriteUInt32NoTag (uint32 value, output);
+ INL static void WriteUInt64NoTag (uint64 value, output);
+ INL static void WriteSInt32NoTag (int32 value, output);
+ INL static void WriteSInt64NoTag (int64 value, output);
+ INL static void WriteFixed32NoTag (uint32 value, output);
+ INL static void WriteFixed64NoTag (uint64 value, output);
+ INL static void WriteSFixed32NoTag(int32 value, output);
+ INL static void WriteSFixed64NoTag(int64 value, output);
+ INL static void WriteFloatNoTag (float value, output);
+ INL static void WriteDoubleNoTag (double value, output);
+ INL static void WriteBoolNoTag (bool value, output);
+ INL static void WriteEnumNoTag (int value, output);
// Write fields, including tags.
static void WriteInt32 (field_number, int32 value, output);
@@ -410,73 +418,59 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
#define output uint8* target
// Like above, but use only *ToArray methods of CodedOutputStream.
- static inline uint8* WriteTagToArray(field_number, WireType type, output) INL;
+ INL static uint8* WriteTagToArray(field_number, WireType type, output);
// Write fields, without tags.
- static inline uint8* WriteInt32NoTagToArray (int32 value, output) INL;
- static inline uint8* WriteInt64NoTagToArray (int64 value, output) INL;
- static inline uint8* WriteUInt32NoTagToArray (uint32 value, output) INL;
- static inline uint8* WriteUInt64NoTagToArray (uint64 value, output) INL;
- static inline uint8* WriteSInt32NoTagToArray (int32 value, output) INL;
- static inline uint8* WriteSInt64NoTagToArray (int64 value, output) INL;
- static inline uint8* WriteFixed32NoTagToArray (uint32 value, output) INL;
- static inline uint8* WriteFixed64NoTagToArray (uint64 value, output) INL;
- static inline uint8* WriteSFixed32NoTagToArray(int32 value, output) INL;
- static inline uint8* WriteSFixed64NoTagToArray(int64 value, output) INL;
- static inline uint8* WriteFloatNoTagToArray (float value, output) INL;
- static inline uint8* WriteDoubleNoTagToArray (double value, output) INL;
- static inline uint8* WriteBoolNoTagToArray (bool value, output) INL;
- static inline uint8* WriteEnumNoTagToArray (int value, output) INL;
+ INL static uint8* WriteInt32NoTagToArray (int32 value, output);
+ INL static uint8* WriteInt64NoTagToArray (int64 value, output);
+ INL static uint8* WriteUInt32NoTagToArray (uint32 value, output);
+ INL static uint8* WriteUInt64NoTagToArray (uint64 value, output);
+ INL static uint8* WriteSInt32NoTagToArray (int32 value, output);
+ INL static uint8* WriteSInt64NoTagToArray (int64 value, output);
+ INL static uint8* WriteFixed32NoTagToArray (uint32 value, output);
+ INL static uint8* WriteFixed64NoTagToArray (uint64 value, output);
+ INL static uint8* WriteSFixed32NoTagToArray(int32 value, output);
+ INL static uint8* WriteSFixed64NoTagToArray(int64 value, output);
+ INL static uint8* WriteFloatNoTagToArray (float value, output);
+ INL static uint8* WriteDoubleNoTagToArray (double value, output);
+ INL static uint8* WriteBoolNoTagToArray (bool value, output);
+ INL static uint8* WriteEnumNoTagToArray (int value, output);
// Write fields, including tags.
- static inline uint8* WriteInt32ToArray(
- field_number, int32 value, output) INL;
- static inline uint8* WriteInt64ToArray(
- field_number, int64 value, output) INL;
- static inline uint8* WriteUInt32ToArray(
- field_number, uint32 value, output) INL;
- static inline uint8* WriteUInt64ToArray(
- field_number, uint64 value, output) INL;
- static inline uint8* WriteSInt32ToArray(
- field_number, int32 value, output) INL;
- static inline uint8* WriteSInt64ToArray(
- field_number, int64 value, output) INL;
- static inline uint8* WriteFixed32ToArray(
- field_number, uint32 value, output) INL;
- static inline uint8* WriteFixed64ToArray(
- field_number, uint64 value, output) INL;
- static inline uint8* WriteSFixed32ToArray(
- field_number, int32 value, output) INL;
- static inline uint8* WriteSFixed64ToArray(
- field_number, int64 value, output) INL;
- static inline uint8* WriteFloatToArray(
- field_number, float value, output) INL;
- static inline uint8* WriteDoubleToArray(
- field_number, double value, output) INL;
- static inline uint8* WriteBoolToArray(
- field_number, bool value, output) INL;
- static inline uint8* WriteEnumToArray(
- field_number, int value, output) INL;
-
- static inline uint8* WriteStringToArray(
- field_number, const string& value, output) INL;
- static inline uint8* WriteBytesToArray(
- field_number, const string& value, output) INL;
-
- static inline uint8* WriteGroupToArray(
- field_number, const MessageLite& value, output) INL;
- static inline uint8* WriteMessageToArray(
- field_number, const MessageLite& value, output) INL;
+ INL static uint8* WriteInt32ToArray(field_number, int32 value, output);
+ INL static uint8* WriteInt64ToArray(field_number, int64 value, output);
+ INL static uint8* WriteUInt32ToArray(field_number, uint32 value, output);
+ INL static uint8* WriteUInt64ToArray(field_number, uint64 value, output);
+ INL static uint8* WriteSInt32ToArray(field_number, int32 value, output);
+ INL static uint8* WriteSInt64ToArray(field_number, int64 value, output);
+ INL static uint8* WriteFixed32ToArray(field_number, uint32 value, output);
+ INL static uint8* WriteFixed64ToArray(field_number, uint64 value, output);
+ INL static uint8* WriteSFixed32ToArray(field_number, int32 value, output);
+ INL static uint8* WriteSFixed64ToArray(field_number, int64 value, output);
+ INL static uint8* WriteFloatToArray(field_number, float value, output);
+ INL static uint8* WriteDoubleToArray(field_number, double value, output);
+ INL static uint8* WriteBoolToArray(field_number, bool value, output);
+ INL static uint8* WriteEnumToArray(field_number, int value, output);
+
+ INL static uint8* WriteStringToArray(
+ field_number, const string& value, output);
+ INL static uint8* WriteBytesToArray(
+ field_number, const string& value, output);
+
+ INL static uint8* WriteGroupToArray(
+ field_number, const MessageLite& value, output);
+ INL static uint8* WriteMessageToArray(
+ field_number, const MessageLite& value, output);
// Like above, but de-virtualize the call to SerializeWithCachedSizes(). The
// pointer must point at an instance of MessageType, *not* a subclass (or
// the subclass must not override SerializeWithCachedSizes()).
template<typename MessageType>
- static inline uint8* WriteGroupNoVirtualToArray(
- field_number, const MessageType& value, output) INL;
+ INL static uint8* WriteGroupNoVirtualToArray(
+ field_number, const MessageType& value, output);
template<typename MessageType>
- static inline uint8* WriteMessageNoVirtualToArray(
- field_number, const MessageType& value, output) INL;
+ INL static uint8* WriteMessageNoVirtualToArray(
+ field_number, const MessageType& value, output);
#undef output
#undef input
@@ -527,18 +521,17 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
// A helper method for the repeated primitive reader. This method has
// optimizations for primitive types that have fixed size on the wire, and
// can be read using potentially faster paths.
- template <typename CType, enum FieldType DeclaredType>
- static inline bool ReadRepeatedFixedSizePrimitive(
+ template <typename CType, enum FieldType DeclaredType> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static bool ReadRepeatedFixedSizePrimitive(
int tag_size,
uint32 tag,
google::protobuf::io::CodedInputStream* input,
- RepeatedField<CType>* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ RepeatedField<CType>* value);
// Like ReadRepeatedFixedSizePrimitive but for packed primitive fields.
- template <typename CType, enum FieldType DeclaredType>
- static inline bool ReadPackedFixedSizePrimitive(
- google::protobuf::io::CodedInputStream* input,
- RepeatedField<CType>* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ template <typename CType, enum FieldType DeclaredType> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static bool ReadPackedFixedSizePrimitive(google::protobuf::io::CodedInputStream* input,
+ RepeatedField<CType>* value);
static const CppType kFieldTypeToCppTypeMap[];
static const WireFormatLite::WireType kWireTypeForFieldType[];
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
index d073ff92..991c3d04 100644
--- a/src/google/protobuf/wire_format_lite_inl.h
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -43,6 +43,7 @@
#include <string>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/message_lite.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/wire_format_lite.h>
diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc
index aef22b29..15c37556 100644
--- a/src/google/protobuf/wire_format_unittest.cc
+++ b/src/google/protobuf/wire_format_unittest.cc
@@ -40,8 +40,10 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/unittest_proto3_arena.pb.h>
#include <google/protobuf/unittest_mset.pb.h>
+#include <google/protobuf/unittest_mset_wire_format.pb.h>
#include <google/protobuf/test_util.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
@@ -419,7 +421,7 @@ const int kUnknownTypeId = 1550055;
TEST(WireFormatTest, SerializeMessageSet) {
// Set up a TestMessageSet with two known messages and an unknown one.
- unittest::TestMessageSet message_set;
+ proto2_wireformat_unittest::TestMessageSet message_set;
message_set.MutableExtension(
unittest::TestMessageSetExtension1::message_set_extension)->set_i(123);
message_set.MutableExtension(
@@ -462,7 +464,7 @@ TEST(WireFormatTest, SerializeMessageSetVariousWaysAreEqual) {
// Set up a TestMessageSet with two known messages and an unknown one, as
// above.
- unittest::TestMessageSet message_set;
+ proto2_wireformat_unittest::TestMessageSet message_set;
message_set.MutableExtension(
unittest::TestMessageSetExtension1::message_set_extension)->set_i(123);
message_set.MutableExtension(
@@ -539,7 +541,7 @@ TEST(WireFormatTest, ParseMessageSet) {
ASSERT_TRUE(raw.SerializeToString(&data));
// Parse as a TestMessageSet and check the contents.
- unittest::TestMessageSet message_set;
+ proto2_wireformat_unittest::TestMessageSet message_set;
ASSERT_TRUE(message_set.ParseFromString(data));
EXPECT_EQ(123, message_set.GetExtension(
@@ -553,7 +555,7 @@ TEST(WireFormatTest, ParseMessageSet) {
EXPECT_EQ("bar", message_set.unknown_fields().field(0).length_delimited());
// Also parse using WireFormat.
- unittest::TestMessageSet dynamic_message_set;
+ proto2_wireformat_unittest::TestMessageSet dynamic_message_set;
io::CodedInputStream input(reinterpret_cast<const uint8*>(data.data()),
data.size());
ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &dynamic_message_set));
@@ -583,7 +585,7 @@ TEST(WireFormatTest, ParseMessageSetWithReverseTagOrder) {
coded_output.WriteTag(WireFormatLite::kMessageSetItemEndTag);
}
{
- unittest::TestMessageSet message_set;
+ proto2_wireformat_unittest::TestMessageSet message_set;
ASSERT_TRUE(message_set.ParseFromString(data));
EXPECT_EQ(123, message_set.GetExtension(
@@ -591,7 +593,7 @@ TEST(WireFormatTest, ParseMessageSetWithReverseTagOrder) {
}
{
// Test parse the message via Reflection.
- unittest::TestMessageSet message_set;
+ proto2_wireformat_unittest::TestMessageSet message_set;
io::CodedInputStream input(
reinterpret_cast<const uint8*>(data.data()), data.size());
EXPECT_TRUE(WireFormat::ParseAndMergePartial(&input, &message_set));
@@ -603,7 +605,7 @@ TEST(WireFormatTest, ParseMessageSetWithReverseTagOrder) {
}
TEST(WireFormatTest, ParseBrokenMessageSet) {
- unittest::TestMessageSet message_set;
+ proto2_wireformat_unittest::TestMessageSet message_set;
string input("goodbye"); // Invalid wire format data.
EXPECT_FALSE(message_set.ParseFromString(input));
}
diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc
index db75db15..b2a7e970 100644
--- a/src/google/protobuf/wrappers.pb.cc
+++ b/src/google/protobuf/wrappers.pb.cc
@@ -262,9 +262,10 @@ void protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto() {
"e\030\001 \001(\004\"\033\n\nInt32Value\022\r\n\005value\030\001 \001(\005\"\034\n\013"
"UInt32Value\022\r\n\005value\030\001 \001(\r\"\032\n\tBoolValue\022"
"\r\n\005value\030\001 \001(\010\"\034\n\013StringValue\022\r\n\005value\030\001"
- " \001(\t\"\033\n\nBytesValue\022\r\n\005value\030\001 \001(\014BM\n\023com"
- ".google.protobufB\rWrappersProtoP\001\242\002\003GPB\252"
- "\002\036Google.Protobuf.WellKnownTypesb\006proto3", 400);
+ " \001(\t\"\033\n\nBytesValue\022\r\n\005value\030\001 \001(\014BP\n\023com"
+ ".google.protobufB\rWrappersProtoP\001\240\001\001\242\002\003G"
+ "PB\252\002\036Google.Protobuf.WellKnownTypesb\006pro"
+ "to3", 403);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/wrappers.proto", &protobuf_RegisterTypes);
DoubleValue::default_instance_ = new DoubleValue();
@@ -1967,10 +1968,10 @@ bool StringValue::MergePartialFromCodedStream(
if (tag == 10) {
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_value()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->value().data(), this->value().length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "google.protobuf.StringValue.value");
+ ::google::protobuf::internal::WireFormatLite::PARSE,
+ "google.protobuf.StringValue.value"));
} else {
goto handle_unusual;
}
@@ -2004,9 +2005,9 @@ void StringValue::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_start:google.protobuf.StringValue)
// optional string value = 1;
if (this->value().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->value().data(), this->value().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.StringValue.value");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->value(), output);
@@ -2020,9 +2021,9 @@ void StringValue::SerializeWithCachedSizes(
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.StringValue)
// optional string value = 1;
if (this->value().size() > 0) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->value().data(), this->value().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
"google.protobuf.StringValue.value");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h
index 387ebd7c..15bcc7a2 100644
--- a/src/google/protobuf/wrappers.pb.h
+++ b/src/google/protobuf/wrappers.pb.h
@@ -37,15 +37,15 @@ void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+class BoolValue;
+class BytesValue;
class DoubleValue;
class FloatValue;
-class Int64Value;
-class UInt64Value;
class Int32Value;
-class UInt32Value;
-class BoolValue;
+class Int64Value;
class StringValue;
-class BytesValue;
+class UInt32Value;
+class UInt64Value;
// ===================================================================
diff --git a/src/google/protobuf/wrappers.proto b/src/google/protobuf/wrappers.proto
index 6d3181bf..a1d6e446 100644
--- a/src/google/protobuf/wrappers.proto
+++ b/src/google/protobuf/wrappers.proto
@@ -37,62 +37,80 @@ syntax = "proto3";
package google.protobuf;
+option java_generate_equals_and_hash = true;
option java_multiple_files = true;
option java_outer_classname = "WrappersProto";
option java_package = "com.google.protobuf";
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
option objc_class_prefix = "GPB";
-
-// Wrapper message for double.
+// Wrapper message for `double`.
+//
+// The JSON representation for `DoubleValue` is JSON number.
message DoubleValue {
// The double value.
double value = 1;
}
-// Wrapper message for float.
+// Wrapper message for `float`.
+//
+// The JSON representation for `FloatValue` is JSON number.
message FloatValue {
// The float value.
float value = 1;
}
-// Wrapper message for int64.
+// Wrapper message for `int64`.
+//
+// The JSON representation for `Int64Value` is JSON string.
message Int64Value {
// The int64 value.
int64 value = 1;
}
-// Wrapper message for uint64.
+// Wrapper message for `uint64`.
+//
+// The JSON representation for `UInt64Value` is JSON string.
message UInt64Value {
// The uint64 value.
uint64 value = 1;
}
-// Wrapper message for int32.
+// Wrapper message for `int32`.
+//
+// The JSON representation for `Int32Value` is JSON number.
message Int32Value {
// The int32 value.
int32 value = 1;
}
-// Wrapper message for uint32.
+// Wrapper message for `uint32`.
+//
+// The JSON representation for `UInt32Value` is JSON number.
message UInt32Value {
// The uint32 value.
uint32 value = 1;
}
-// Wrapper message for bool.
+// Wrapper message for `bool`.
+//
+// The JSON representation for `BoolValue` is JSON `true` and `false`.
message BoolValue {
// The bool value.
bool value = 1;
}
-// Wrapper message for string.
+// Wrapper message for `string`.
+//
+// The JSON representation for `StringValue` is JSON string.
message StringValue {
// The string value.
string value = 1;
}
-// Wrapper message for bytes.
+// Wrapper message for `bytes`.
+//
+// The JSON representation for `BytesValue` is JSON string.
message BytesValue {
// The bytes value.
bytes value = 1;
diff --git a/travis.sh b/travis.sh
index a5208fe3..b4a908dd 100755
--- a/travis.sh
+++ b/travis.sh
@@ -113,12 +113,14 @@ build_javanano_oracle7() {
internal_install_python_deps() {
sudo pip install tox
- # Only install Python2.6 on Linux.
+ # Only install Python2.6/3.x on Linux.
if [ $(uname -s) == "Linux" ]; then
sudo apt-get install -y python-software-properties # for apt-add-repository
sudo apt-add-repository -y ppa:fkrull/deadsnakes
sudo apt-get update -qq
sudo apt-get install -y python2.6 python2.6-dev
+ sudo apt-get install -y python3.3 python3.3-dev
+ sudo apt-get install -y python3.4 python3.4-dev
fi
}
@@ -127,9 +129,9 @@ build_python() {
internal_build_cpp
internal_install_python_deps
cd python
- # Only test Python 2.6 on Linux
+ # Only test Python 2.6/3.x on Linux
if [ $(uname -s) == "Linux" ]; then
- envlist=py26-python,py27-python
+ envlist=py\{26,27,33,34\}-python
else
envlist=py27-python
fi
@@ -143,9 +145,9 @@ build_python_cpp() {
export LD_LIBRARY_PATH=../src/.libs # for Linux
export DYLD_LIBRARY_PATH=../src/.libs # for OS X
cd python
- # Only test Python 2.6 on Linux
+ # Only test Python 2.6/3.x on Linux
if [ $(uname -s) == "Linux" ]; then
- envlist=py26-cpp,py27-cpp
+ envlist=py\{26,27,33,34\}-cpp
else
envlist=py27-cpp
fi
diff --git a/update_file_lists.sh b/update_file_lists.sh
index 34443456..d76a1610 100755
--- a/update_file_lists.sh
+++ b/update_file_lists.sh
@@ -27,6 +27,10 @@ get_source_files() {
get_variable_value $@ | grep "cc$"
}
+get_proto_files_blacklisted() {
+ get_proto_files $@ | sed '/^google\/protobuf\/unittest_enormous_descriptor.proto$/d'
+}
+
get_proto_files() {
get_variable_value $@ | grep "pb.cc$" | sed "s/pb.cc/proto/"
}
@@ -53,10 +57,13 @@ LIBPROTOBUF_SOURCES=$(get_source_files $MAKEFILE libprotobuf_la_SOURCES)
LIBPROTOC_SOURCES=$(get_source_files $MAKEFILE libprotoc_la_SOURCES)
LITE_PROTOS=$(get_proto_files $MAKEFILE protoc_lite_outputs)
PROTOS=$(get_proto_files $MAKEFILE protoc_outputs)
+PROTOS_BLACKLISTED=$(get_proto_files_blacklisted $MAKEFILE protoc_outputs)
WKT_PROTOS=$(get_variable_value $MAKEFILE nobase_dist_proto_DATA)
COMMON_TEST_SOURCES=$(get_source_files $MAKEFILE COMMON_TEST_SOURCES)
+COMMON_LITE_TEST_SOURCES=$(get_source_files $MAKEFILE COMMON_LITE_TEST_SOURCES)
TEST_SOURCES=$(get_source_files $MAKEFILE protobuf_test_SOURCES)
LITE_TEST_SOURCES=$(get_source_files $MAKEFILE protobuf_lite_test_SOURCES)
+LITE_ARENA_TEST_SOURCES=$(get_source_files $MAKEFILE protobuf_lite_arena_test_SOURCES)
TEST_PLUGIN_SOURCES=$(get_source_files $MAKEFILE test_plugin_SOURCES)
################################################################################
@@ -110,10 +117,12 @@ set_cmake_value $CMAKE_DIR/libprotobuf-lite.cmake libprotobuf_lite_files $CMAKE_
set_cmake_value $CMAKE_DIR/libprotobuf.cmake libprotobuf_files $CMAKE_PREFIX $LIBPROTOBUF_SOURCES
set_cmake_value $CMAKE_DIR/libprotoc.cmake libprotoc_files $CMAKE_PREFIX $LIBPROTOC_SOURCES
set_cmake_value $CMAKE_DIR/tests.cmake lite_test_protos "" $LITE_PROTOS
-set_cmake_value $CMAKE_DIR/tests.cmake tests_protos "" $PROTOS
+set_cmake_value $CMAKE_DIR/tests.cmake tests_protos "" $PROTOS_BLACKLISTED
set_cmake_value $CMAKE_DIR/tests.cmake common_test_files $CMAKE_PREFIX $COMMON_TEST_SOURCES
+set_cmake_value $CMAKE_DIR/tests.cmake common_lite_test_files $CMAKE_PREFIX $COMMON_LITE_TEST_SOURCES
set_cmake_value $CMAKE_DIR/tests.cmake tests_files $CMAKE_PREFIX $TEST_SOURCES
set_cmake_value $CMAKE_DIR/tests.cmake lite_test_files $CMAKE_PREFIX $LITE_TEST_SOURCES
+set_cmake_value $CMAKE_DIR/tests.cmake lite_arena_test_files $CMAKE_PREFIX $LITE_ARENA_TEST_SOURCES
# Generate extract_includes.bat
echo "mkdir include" > $EXTRACT_INCLUDES_BAT
@@ -133,11 +142,6 @@ done
# Update bazel BUILD files.
################################################################################
-BAZEL_BUILD=./BUILD
-[ -f "$BAZEL_BUILD" ] || {
- echo "Cannot find: $BAZEL_BUILD"
- exit 1
-}
set_bazel_value() {
local FILENAME=$1
local VARNAME=$2
@@ -169,14 +173,19 @@ set_bazel_value() {
}
+BAZEL_BUILD=./BUILD
BAZEL_PREFIX="src/"
-set_bazel_value $BAZEL_BUILD protobuf_lite_srcs $BAZEL_PREFIX $LIBPROTOBUF_LITE_SOURCES
-set_bazel_value $BAZEL_BUILD protobuf_srcs $BAZEL_PREFIX $LIBPROTOBUF_SOURCES
-set_bazel_value $BAZEL_BUILD protoc_lib_srcs $BAZEL_PREFIX $LIBPROTOC_SOURCES
-set_bazel_value $BAZEL_BUILD lite_test_protos "" $LITE_PROTOS
-set_bazel_value $BAZEL_BUILD well_known_protos "" $WKT_PROTOS
-set_bazel_value $BAZEL_BUILD test_protos "" $PROTOS
-set_bazel_value $BAZEL_BUILD common_test_srcs $BAZEL_PREFIX $COMMON_TEST_SOURCES
-set_bazel_value $BAZEL_BUILD test_srcs $BAZEL_PREFIX $TEST_SOURCES
-set_bazel_value $BAZEL_BUILD test_plugin_srcs $BAZEL_PREFIX $TEST_PLUGIN_SOURCES
+if [ -f "$BAZEL_BUILD" ]; then
+ set_bazel_value $BAZEL_BUILD protobuf_lite_srcs $BAZEL_PREFIX $LIBPROTOBUF_LITE_SOURCES
+ set_bazel_value $BAZEL_BUILD protobuf_srcs $BAZEL_PREFIX $LIBPROTOBUF_SOURCES
+ set_bazel_value $BAZEL_BUILD protoc_lib_srcs $BAZEL_PREFIX $LIBPROTOC_SOURCES
+ set_bazel_value $BAZEL_BUILD lite_test_protos "" $LITE_PROTOS
+ set_bazel_value $BAZEL_BUILD well_known_protos "" $WKT_PROTOS
+ set_bazel_value $BAZEL_BUILD test_protos "" $PROTOS
+ set_bazel_value $BAZEL_BUILD common_test_srcs $BAZEL_PREFIX $COMMON_TEST_SOURCES
+ set_bazel_value $BAZEL_BUILD test_srcs $BAZEL_PREFIX $TEST_SOURCES
+ set_bazel_value $BAZEL_BUILD test_plugin_srcs $BAZEL_PREFIX $TEST_PLUGIN_SOURCES
+else
+ echo "Skipped BUILD file update."
+fi