aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--.travis.yml33
-rw-r--r--BUILD2
-rw-r--r--CHANGES.txt132
-rw-r--r--Makefile.am169
-rw-r--r--Protobuf.podspec3
-rw-r--r--README.md2
-rw-r--r--WORKSPACE24
-rw-r--r--appveyor.bat11
-rw-r--r--appveyor.yml19
-rwxr-xr-xautogen.sh13
-rw-r--r--benchmarks/readme.txt22
-rw-r--r--cmake/CMakeLists.txt6
-rw-r--r--cmake/examples.cmake114
-rw-r--r--cmake/extract_includes.bat.in1
-rw-r--r--cmake/install.cmake2
-rw-r--r--cmake/libprotobuf.cmake5
-rw-r--r--cmake/protobuf-config-version.cmake.in2
-rw-r--r--cmake/protobuf-config.cmake.in3
-rw-r--r--cmake/protobuf-module.cmake.in1
-rw-r--r--cmake/protobuf-options.cmake14
-rw-r--r--configure.ac2
-rw-r--r--conformance/Makefile.am92
-rw-r--r--conformance/conformance.proto12
-rwxr-xr-xconformance/conformance_ruby.rb2
-rw-r--r--conformance/conformance_test.cc230
-rw-r--r--conformance/conformance_test.h3
-rw-r--r--conformance/failure_list_cpp.txt12
-rw-r--r--conformance/failure_list_csharp.txt7
-rw-r--r--conformance/failure_list_java.txt8
-rw-r--r--conformance/failure_list_objc.txt6
-rw-r--r--conformance/failure_list_python.txt5
-rw-r--r--conformance/failure_list_python_cpp.txt5
-rw-r--r--conformance/failure_list_ruby.txt14
-rw-r--r--csharp/.gitignore21
-rw-r--r--csharp/Google.Protobuf.Tools.nuspec2
-rw-r--r--csharp/README.md4
-rw-r--r--csharp/build_packages.bat7
-rwxr-xr-xcsharp/buildall.sh15
-rw-r--r--csharp/src/AddressBook/AddressBook.csproj75
-rw-r--r--csharp/src/AddressBook/AddressBook.xproj19
-rw-r--r--csharp/src/AddressBook/Properties/AssemblyInfo.cs18
-rw-r--r--csharp/src/AddressBook/SampleUsage.cs2
-rw-r--r--csharp/src/AddressBook/app.config3
-rw-r--r--csharp/src/AddressBook/project.json20
-rw-r--r--csharp/src/Google.Protobuf.Conformance/App.config6
-rw-r--r--csharp/src/Google.Protobuf.Conformance/Conformance.cs498
-rw-r--r--csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj61
-rw-r--r--csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.xproj19
-rw-r--r--csharp/src/Google.Protobuf.Conformance/project.json19
-rw-r--r--csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj68
-rw-r--r--csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.xproj19
-rw-r--r--csharp/src/Google.Protobuf.JsonDump/Program.cs3
-rw-r--r--csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs19
-rw-r--r--csharp/src/Google.Protobuf.JsonDump/app.config3
-rw-r--r--csharp/src/Google.Protobuf.JsonDump/project.json19
-rw-r--r--csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs90
-rw-r--r--csharp/src/Google.Protobuf.Test/FieldCodecTest.cs3
-rw-r--r--csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj143
-rw-r--r--csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.xproj19
-rw-r--r--csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs6
-rw-r--r--csharp/src/Google.Protobuf.Test/Properties/AppManifest.xml6
-rw-r--r--csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs20
-rw-r--r--csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs2
-rw-r--r--csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs4
-rw-r--r--csharp/src/Google.Protobuf.Test/packages.config5
-rw-r--r--csharp/src/Google.Protobuf.Test/project.json44
-rw-r--r--csharp/src/Google.Protobuf.sln65
-rw-r--r--csharp/src/Google.Protobuf/CodedInputStream.cs4
-rw-r--r--csharp/src/Google.Protobuf/Collections/MapField.cs31
-rw-r--r--csharp/src/Google.Protobuf/Collections/RepeatedField.cs113
-rw-r--r--csharp/src/Google.Protobuf/Google.Protobuf.csproj168
-rw-r--r--csharp/src/Google.Protobuf/Google.Protobuf.nuspec54
-rw-r--r--csharp/src/Google.Protobuf/Google.Protobuf.xproj19
-rw-r--r--csharp/src/Google.Protobuf/JsonFormatter.cs12
-rw-r--r--csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs18
-rw-r--r--csharp/src/Google.Protobuf/Reflection/Descriptor.cs6
-rw-r--r--csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs13
-rw-r--r--csharp/src/Google.Protobuf/packages.config4
-rw-r--r--csharp/src/Google.Protobuf/project.json65
-rw-r--r--docs/third_party.md1
-rw-r--r--editors/protobuf-mode.el3
-rw-r--r--examples/CMakeLists.txt126
-rwxr-xr-xgenerate_descriptor_proto.sh2
-rw-r--r--gmock.BUILD20
-rwxr-xr-xjava/compatibility_tests/v2.5.0/test.sh14
-rw-r--r--java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RepeatedFieldBuilderTest.java191
-rw-r--r--java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/SingleFieldBuilderTest.java156
-rw-r--r--java/core/pom.xml2
-rw-r--r--java/core/src/main/java/com/google/protobuf/AbstractMessage.java2
-rw-r--r--java/core/src/main/java/com/google/protobuf/ByteOutput.java4
-rw-r--r--java/core/src/main/java/com/google/protobuf/CodedOutputStream.java38
-rw-r--r--java/core/src/main/java/com/google/protobuf/DynamicMessage.java8
-rw-r--r--java/core/src/main/java/com/google/protobuf/GeneratedMessage.java8
-rw-r--r--java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java2716
-rw-r--r--java/core/src/main/java/com/google/protobuf/Internal.java20
-rw-r--r--java/core/src/main/java/com/google/protobuf/Parser.java2
-rw-r--r--java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java4
-rw-r--r--java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java50
-rw-r--r--java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java4
-rw-r--r--java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java3
-rw-r--r--java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java190
-rw-r--r--java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java155
-rw-r--r--java/lite/pom.xml2
-rw-r--r--java/pom.xml30
-rw-r--r--java/util/pom.xml2
-rw-r--r--java/util/src/main/java/com/google/protobuf/util/JsonFormat.java68
-rw-r--r--java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java38
-rw-r--r--javanano/pom.xml6
-rw-r--r--jenkins/docker/Dockerfile33
-rwxr-xr-xjenkins/pull_request_in_docker.sh4
-rw-r--r--js/README.md3
-rw-r--r--js/commonjs/export.js4
-rw-r--r--js/debug.js6
-rw-r--r--js/map.js87
-rw-r--r--js/message.js91
-rw-r--r--js/message_test.js107
-rw-r--r--js/package.json2
-rw-r--r--js/proto3_test.js39
-rw-r--r--js/test.proto1
-rwxr-xr-xobjectivec/DevTools/compile_testing_protos.sh91
-rw-r--r--objectivec/GPBArray.h1448
-rw-r--r--objectivec/GPBArray.m20
-rw-r--r--objectivec/GPBBootstrap.h39
-rw-r--r--objectivec/GPBCodedInputStream.h199
-rw-r--r--objectivec/GPBCodedOutputStream.h599
-rw-r--r--objectivec/GPBCodedOutputStream.m39
-rw-r--r--objectivec/GPBDescriptor.h162
-rw-r--r--objectivec/GPBDescriptor.m114
-rw-r--r--objectivec/GPBDescriptor_PackagePrivate.h8
-rw-r--r--objectivec/GPBDictionary.h6538
-rw-r--r--objectivec/GPBExtensionRegistry.h71
-rw-r--r--objectivec/GPBMessage.h526
-rw-r--r--objectivec/GPBMessage.m5
-rw-r--r--objectivec/GPBMessage_PackagePrivate.h4
-rw-r--r--objectivec/GPBRootObject.h13
-rw-r--r--objectivec/GPBRuntimeTypes.h72
-rw-r--r--objectivec/GPBUnknownField.h63
-rw-r--r--objectivec/GPBUnknownFieldSet.h47
-rw-r--r--objectivec/GPBUtilities.h493
-rw-r--r--objectivec/GPBUtilities.m84
-rw-r--r--objectivec/GPBUtilities_PackagePrivate.h8
-rw-r--r--objectivec/GPBWellKnownTypes.h175
-rw-r--r--objectivec/GPBWellKnownTypes.m135
-rw-r--r--objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj6
-rw-r--r--objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj6
-rw-r--r--objectivec/Tests/GPBCodedOuputStreamTests.m86
-rw-r--r--objectivec/Tests/GPBDescriptorTests.m29
-rw-r--r--objectivec/Tests/GPBMessageTests+Runtime.m399
-rw-r--r--objectivec/Tests/GPBUnittestProtos.m9
-rw-r--r--objectivec/Tests/GPBUnittestProtos2.m (renamed from csharp/src/Google.Protobuf.Conformance/Properties/AssemblyInfo.cs)24
-rw-r--r--objectivec/Tests/GPBWellKnownTypesTest.m56
-rw-r--r--objectivec/Tests/unittest_cycle.proto6
-rw-r--r--objectivec/Tests/unittest_extension_chain_a.proto51
-rw-r--r--objectivec/Tests/unittest_extension_chain_b.proto47
-rw-r--r--objectivec/Tests/unittest_extension_chain_c.proto45
-rw-r--r--objectivec/Tests/unittest_extension_chain_d.proto49
-rw-r--r--objectivec/Tests/unittest_extension_chain_e.proto40
-rw-r--r--objectivec/Tests/unittest_extension_chain_f.proto44
-rw-r--r--objectivec/Tests/unittest_extension_chain_g.proto41
-rw-r--r--objectivec/Tests/unittest_objc.proto9
-rw-r--r--objectivec/google/protobuf/Any.pbobjc.h206
-rw-r--r--objectivec/google/protobuf/Any.pbobjc.m8
-rw-r--r--objectivec/google/protobuf/Api.pbobjc.h306
-rw-r--r--objectivec/google/protobuf/Api.pbobjc.m29
-rw-r--r--objectivec/google/protobuf/Duration.pbobjc.h122
-rw-r--r--objectivec/google/protobuf/Duration.pbobjc.m6
-rw-r--r--objectivec/google/protobuf/Empty.pbobjc.h40
-rw-r--r--objectivec/google/protobuf/Empty.pbobjc.m6
-rw-r--r--objectivec/google/protobuf/FieldMask.pbobjc.h428
-rw-r--r--objectivec/google/protobuf/FieldMask.pbobjc.m6
-rw-r--r--objectivec/google/protobuf/SourceContext.pbobjc.h32
-rw-r--r--objectivec/google/protobuf/SourceContext.pbobjc.m6
-rw-r--r--objectivec/google/protobuf/Struct.pbobjc.h126
-rw-r--r--objectivec/google/protobuf/Struct.pbobjc.m14
-rw-r--r--objectivec/google/protobuf/Timestamp.pbobjc.h146
-rw-r--r--objectivec/google/protobuf/Timestamp.pbobjc.m6
-rw-r--r--objectivec/google/protobuf/Type.pbobjc.h276
-rw-r--r--objectivec/google/protobuf/Type.pbobjc.m35
-rw-r--r--objectivec/google/protobuf/Wrappers.pbobjc.h110
-rw-r--r--objectivec/google/protobuf/Wrappers.pbobjc.m22
-rw-r--r--protobuf.bzl58
-rw-r--r--protoc-artifacts/Dockerfile4
-rw-r--r--protoc-artifacts/README.md19
-rwxr-xr-xprotoc-artifacts/build-protoc.sh27
-rwxr-xr-xprotoc-artifacts/build-zip.sh108
-rw-r--r--protoc-artifacts/pom.xml3
-rwxr-xr-xpython/google/protobuf/__init__.py2
-rw-r--r--python/google/protobuf/internal/json_format_test.py6
-rwxr-xr-xpython/google/protobuf/internal/python_message.py26
-rwxr-xr-xpython/google/protobuf/internal/reflection_test.py3
-rw-r--r--python/google/protobuf/internal/symbol_database_test.py26
-rw-r--r--python/google/protobuf/json_format.py2
-rw-r--r--python/google/protobuf/pyext/cpp_message.py6
-rw-r--r--python/google/protobuf/pyext/map_container.cc3
-rw-r--r--python/google/protobuf/pyext/message.cc16
-rw-r--r--python/google/protobuf/pyext/message.h4
-rw-r--r--python/google/protobuf/pyext/repeated_composite_container.cc4
-rwxr-xr-xpython/google/protobuf/reflection.py8
-rw-r--r--python/google/protobuf/symbol_database.py82
-rw-r--r--python/setup.cfg2
-rw-r--r--ruby/Rakefile7
-rw-r--r--ruby/ext/google/protobuf_c/encode_decode.c113
-rw-r--r--ruby/ext/google/protobuf_c/map.c20
-rw-r--r--ruby/ext/google/protobuf_c/protobuf.c2
-rw-r--r--ruby/ext/google/protobuf_c/protobuf.h5
-rw-r--r--ruby/ext/google/protobuf_c/repeated_field.c5
-rw-r--r--ruby/ext/google/protobuf_c/storage.c39
-rw-r--r--ruby/ext/google/protobuf_c/upb.c4
-rw-r--r--ruby/google-protobuf.gemspec2
-rw-r--r--ruby/lib/google/protobuf.rb2
-rw-r--r--ruby/lib/google/protobuf/well_known_types.rb212
-rw-r--r--ruby/pom.xml2
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java4
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java4
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java4
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/Utils.java37
-rw-r--r--ruby/tests/basic.rb48
-rw-r--r--ruby/tests/generated_code.proto2
-rw-r--r--ruby/tests/generated_code_test.rb4
-rw-r--r--ruby/tests/test_import.proto5
-rw-r--r--ruby/tests/well_known_types_test.rb122
-rwxr-xr-xruby/travis-test.sh2
-rw-r--r--src/Makefile.am45
-rw-r--r--src/google/protobuf/any.pb.cc21
-rw-r--r--src/google/protobuf/api.pb.cc39
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc5
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc26
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.cc205
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.h4
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc12
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_enum.cc4
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_generator.cc3
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_options.h9
-rw-r--r--src/google/protobuf/compiler/java/java_file.cc18
-rw-r--r--src/google/protobuf/compiler/java/java_generator.cc2
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc62
-rw-r--r--src/google/protobuf/compiler/java/java_message_builder.cc93
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.cc2
-rw-r--r--src/google/protobuf/compiler/java/java_string_field.cc6
-rwxr-xr-xsrc/google/protobuf/compiler/js/js_generator.cc160
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_enum.cc18
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc14
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_extension.cc4
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_field.cc8
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_file.cc455
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_file.h15
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_generator.cc76
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_generator.h11
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers.cc413
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers.h67
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_map_field.cc2
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_message.cc18
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_oneof.cc8
-rw-r--r--src/google/protobuf/compiler/parser.cc1
-rw-r--r--src/google/protobuf/compiler/plugin.pb.cc37
-rw-r--r--src/google/protobuf/compiler/python/python_generator.cc60
-rw-r--r--src/google/protobuf/compiler/python/python_plugin_unittest.cc48
-rw-r--r--src/google/protobuf/compiler/ruby/ruby_generated_code_pb.rb (renamed from src/google/protobuf/compiler/ruby/ruby_generated_code.rb)0
-rw-r--r--src/google/protobuf/compiler/ruby/ruby_generator.cc60
-rw-r--r--src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc4
-rw-r--r--src/google/protobuf/compiler/subprocess.cc12
-rw-r--r--src/google/protobuf/descriptor.pb.cc237
-rw-r--r--src/google/protobuf/descriptor.proto1
-rw-r--r--src/google/protobuf/duration.pb.cc23
-rw-r--r--src/google/protobuf/empty.pb.cc21
-rw-r--r--src/google/protobuf/extension_set_heavy.cc2
-rw-r--r--src/google/protobuf/field_mask.pb.cc21
-rw-r--r--src/google/protobuf/generated_message_util.cc6
-rw-r--r--src/google/protobuf/generated_message_util.h11
-rw-r--r--src/google/protobuf/io/coded_stream.cc8
-rw-r--r--src/google/protobuf/io/coded_stream.h47
-rw-r--r--src/google/protobuf/map.h2
-rw-r--r--src/google/protobuf/map_entry_lite.h26
-rw-r--r--src/google/protobuf/map_proto2_unittest.proto20
-rw-r--r--src/google/protobuf/map_test.cc77
-rw-r--r--src/google/protobuf/map_type_handler.h18
-rw-r--r--src/google/protobuf/message.cc2
-rw-r--r--src/google/protobuf/message.h2
-rw-r--r--src/google/protobuf/message_lite.cc2
-rw-r--r--src/google/protobuf/message_lite.h2
-rw-r--r--src/google/protobuf/repeated_field_reflection.h337
-rw-r--r--src/google/protobuf/source_context.pb.cc21
-rw-r--r--src/google/protobuf/struct.pb.cc156
-rw-r--r--src/google/protobuf/stubs/atomicops_internals_generic_gcc.h18
-rw-r--r--src/google/protobuf/stubs/callback.h4
-rw-r--r--src/google/protobuf/stubs/common_unittest.cc2
-rw-r--r--src/google/protobuf/stubs/int128.cc6
-rw-r--r--src/google/protobuf/stubs/map_util.h7
-rw-r--r--src/google/protobuf/stubs/once_unittest.cc5
-rw-r--r--src/google/protobuf/stubs/port.h20
-rw-r--r--src/google/protobuf/testdata/golden_message_mapsbin0 -> 13619 bytes
-rw-r--r--src/google/protobuf/testing/file.cc17
-rw-r--r--src/google/protobuf/text_format.cc14
-rw-r--r--src/google/protobuf/timestamp.pb.cc23
-rw-r--r--src/google/protobuf/type.pb.cc55
-rw-r--r--src/google/protobuf/unknown_field_set.cc28
-rw-r--r--src/google/protobuf/unknown_field_set.h8
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter.cc34
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter.h12
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter_test.cc33
-rw-r--r--src/google/protobuf/util/internal/proto_writer.cc34
-rw-r--r--src/google/protobuf/util/internal/proto_writer.h9
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter.cc2
-rw-r--r--src/google/protobuf/util/json_util.cc60
-rw-r--r--src/google/protobuf/util/json_util.h29
-rw-r--r--src/google/protobuf/util/json_util_test.cc88
-rw-r--r--src/google/protobuf/util/message_differencer.cc3
-rw-r--r--src/google/protobuf/util/time_util.cc9
-rw-r--r--src/google/protobuf/wire_format_lite.cc6
-rw-r--r--src/google/protobuf/wire_format_lite_inl.h10
-rw-r--r--src/google/protobuf/wrappers.pb.cc85
-rwxr-xr-xtests.sh103
314 files changed, 20153 insertions, 5605 deletions
diff --git a/.gitignore b/.gitignore
index 5cb8cba9..052dd14d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -64,6 +64,8 @@ src/protoc
src/unittest_proto_middleman
# Generated test scaffolding
+src/no_warning_test.cc
+src/no-warning-test
src/protobuf*-test
src/test_plugin
src/testzip.*
@@ -108,8 +110,11 @@ conformance/conformance.pb.cc
conformance/conformance.pb.h
conformance/Conformance.pbobjc.h
conformance/Conformance.pbobjc.m
-conformance/conformance.rb
+conformance/conformance_pb.rb
+conformance/failing_tests.txt
conformance/google/
conformance/javac_middleman
conformance/lite/
+conformance/nonexistent_tests.txt
conformance/protoc_middleman
+conformance/succeeding_tests.txt
diff --git a/.travis.yml b/.travis.yml
index 46abbb9e..094235e0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,7 +5,6 @@ sudo: required
# rvm/gemfile/jdk/etc. entries rather than manually doing the work.
language: cpp
os:
- - linux
- osx
# The Objective C build needs Xcode 7.0 or later.
osx_image: xcode7.3
@@ -14,12 +13,9 @@ script:
env:
- CONFIG=cpp
- CONFIG=cpp_distcheck
- - CONFIG=csharp
- CONFIG=golang
- - CONFIG=java_jdk6
- CONFIG=java_jdk7
- CONFIG=java_oracle7
- - CONFIG=javanano_jdk6
- CONFIG=javanano_jdk7
- CONFIG=javanano_oracle7
- CONFIG=javascript
@@ -31,8 +27,6 @@ env:
- CONFIG=objectivec_cocoapods_integration
- CONFIG=python
- CONFIG=python_cpp
- - CONFIG=ruby19
- - CONFIG=ruby20
- CONFIG=ruby21
- CONFIG=ruby22
- CONFIG=jruby
@@ -41,35 +35,32 @@ matrix:
# It's nontrivial to programmatically install a new JDK from the command
# line on OS X, so we rely on testing on Linux for Java code.
- os: osx
- env: CONFIG=java_jdk6
- - os: osx
env: CONFIG=java_jdk7
- os: osx
env: CONFIG=java_oracle7
- os: osx
- env: CONFIG=javanano_jdk6
- - os: osx
env: CONFIG=javanano_jdk7
- os: osx
env: CONFIG=javanano_oracle7
- # Requires installing mono, currently travis.sh is doing that with apt-get
- # which doesn't work on OS X.
- - os: osx
- env: CONFIG=csharp
# Requires installing golang, currently travis.sh is doing that with apt-get
# which doesn't work on OS X.
- os: osx
env: CONFIG=golang
- # OS X/iOS tests of Objective C (needs Xcode, so it won't work on other
- # platforms).
+ include:
+ # The dotnet environment requires Ubuntu 14.04 or 16.04. This
+ # configuration is effectively an "extra" one, outside the
+ # autogenerated matrix.
- os: linux
- env: CONFIG=objectivec_ios_debug
- - os: linux
- env: CONFIG=objectivec_ios_release
+ env: CONFIG=csharp
+ dist: trusty
+ # This test is kept on travis because it doesn't play nicely with other
+ # tests on jenkins running in parallel.
- os: linux
- env: CONFIG=objectivec_osx
+ env: CONFIG=cpp_distcheck
+ # The Java compatibility test currently only runs on Linux because it will
+ # fetch pre-built Linux protoc binaries in the test.
- os: linux
- env: CONFIG=objectivec_cocoapods_integration
+ env: CONFIG=java_compatibility
allow_failures:
# These currently do not work on OS X but are being worked on by @haberman.
- os: osx
diff --git a/BUILD b/BUILD
index 0941d8c4..941ca691 100644
--- a/BUILD
+++ b/BUILD
@@ -2,6 +2,8 @@
licenses(["notice"])
+exports_files(["LICENSE"])
+
################################################################################
# Protobuf Runtime Library
################################################################################
diff --git a/CHANGES.txt b/CHANGES.txt
index 3459cccf..822136c0 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,135 @@
+2016-07-27 version 3.0.0 (C++/Java/Python/Ruby/Objective-C/C#/JavaScript/Lite)
+ General
+ * This log only contains changes since the beta-4 release. Summarized change
+ log since the last stable release (v2.6.1) can be found in the github
+ release page.
+
+ Compatibility Notice
+ * v3.0.0 is the first API stable release of the v3.x series. We do not expect
+ any future API breaking changes.
+ * For C++, Java Lite and Objective-C, source level compatibility is
+ guaranteed. Upgrading from v3.0.0 to newer minor version releases will be
+ source compatible. For example, if your code compiles against protobuf
+ v3.0.0, it will continue to compile after you upgrade protobuf library to
+ v3.1.0.
+ * For other languages, both source level compatibility and binary level
+ compatibility are guaranteed. For example, if you have a Java binary built
+ against protobuf v3.0.0. After switching the protobuf runtime binary to
+ v3.1.0, your built binary should continue to work.
+ * Compatibility is only guaranteed for documented API and documented
+ behaviors. If you are using undocumented API (e.g., use anything in the C++
+ internal namespace), it can be broken by minor version releases in an
+ undetermined manner.
+
+ Ruby
+ * When you assign a string field `a.string_field = "X"`, we now call
+ #encode(UTF-8) on the string and freeze the copy. This saves you from
+ needing to ensure the string is already encoded as UTF-8. It also prevents
+ you from mutating the string after it has been assigned (this is how we
+ ensure it stays valid UTF-8).
+ * The generated file for `foo.proto` is now `foo_pb.rb` instead of just
+ `foo.rb`. This makes it easier to see which imports/requires are from
+ protobuf generated code, and also prevents conflicts with any `foo.rb` file
+ you might have written directly in Ruby. It is a backward-incompatible
+ change: you will need to update all of your `require` statements.
+ * For package names like `foo_bar`, we now translate this to the Ruby module
+ `FooBar`. This is more idiomatic Ruby than what we used to do (`Foo_bar`).
+
+ JavaScript
+ * Scalar fields like numbers and boolean now return defaults instead of
+ `undefined` or `null` when they are unset. You can test for presence
+ explicitly by calling `hasFoo()`, which we now generate for scalar fields.
+
+ Java Lite
+ * Java Lite is now implemented as a separate plugin, maintained in the
+ `javalite` branch. Both lite runtime and protoc artifacts will be available
+ in Maven.
+
+ C#
+ * Target platforms now .NET 4.5, selected portable subsets and .NET Core.
+ * legacy_enum_values option is no longer supported.
+
+2016-07-15 version 3.0.0-beta-4 (C++/Java/Python/Ruby/Objective-C/C#/JavaScript)
+ General
+ * Added a deterministic serialization API for C++. The deterministic
+ serialization guarantees that given a binary, equal messages will be
+ serialized to the same bytes. This allows applications like MapReduce to
+ group equal messages based on the serialized bytes. The deterministic
+ serialization is, however, NOT canonical across languages; it is also
+ unstable across different builds with schema changes due to unknown fields.
+ Users who need canonical serialization, e.g. persistent storage in a
+ canonical form, fingerprinting, etc, should define their own
+ canonicalization specification and implement the serializer using reflection
+ APIs rather than relying on this API.
+ * Added OneofOptions. You can now define custom options for oneof groups.
+ import "google/protobuf/descriptor.proto";
+ extend google.protobuf.OneofOptions {
+ optional int32 my_oneof_extension = 12345;
+ }
+ message Foo {
+ oneof oneof_group {
+ (my_oneof_extension) = 54321;
+ ...
+ }
+ }
+
+ C++ (beta)
+ * Introduced a deterministic serialization API in
+ CodedOutputStream::SetSerializationDeterministic(bool). See the notes about
+ deterministic serialization in the General section.
+ * Added google::protobuf::Map::swap() to swap two map fields.
+ * Fixed a memory leak when calling Reflection::ReleaseMessage() on a message
+ allocated on arena.
+ * Improved error reporting when parsing text format protos.
+ * JSON
+ - Added a new parser option to ignore unknown fields when parsing JSON.
+ - Added convenient methods for message to/from JSON conversion.
+ * Various performance optimizations.
+
+ Java (beta)
+ * File option "java_generate_equals_and_hash" is now deprecated. equals() and
+ hashCode() methods are generated by default.
+ * Added a new JSON printer option "omittingInsignificantWhitespace" to produce
+ a more compact JSON output. The printer will pretty-print by default.
+ * Updated Java runtime to be compatible with 2.5.0/2.6.1 generated protos.
+
+ Python (beta)
+ * Added support to pretty print Any messages in text format.
+ * Added a flag to ignore unknown fields when parsing JSON.
+ * Bugfix: "@type" field of a JSON Any message is now correctly put before
+ other fields.
+
+ Objective-C (beta)
+ * Updated the code to support compiling with more compiler warnings
+ enabled. (Issue 1616)
+ * Exposing more detailed errors for parsing failures. (PR 1623)
+ * Small (breaking) change to the naming of some methods on the support classes
+ for map<>. There were collisions with the system provided KVO support, so
+ the names were changed to avoid those issues. (PR 1699)
+ * Fixed for proper Swift bridging of error handling during parsing. (PR 1712)
+ * Complete support for generating sources that will go into a Framework and
+ depend on generated sources from other Frameworks. (Issue 1457)
+
+ C# (beta)
+ * RepeatedField optimizations.
+ * Support for .NET Core.
+ * Minor bug fixes.
+ * Ability to format a single value in JsonFormatter (advanced usage only).
+ * Modifications to attributes applied to generated code.
+
+ Javascript (alpha)
+ * Maps now have a real map API instead of being treated as repeated fields.
+ * Well-known types are now provided in the google-protobuf package, and the
+ code generator knows to require() them from that package.
+ * Bugfix: non-canonical varints are correctly decoded.
+
+ Ruby (alpha)
+ * Accessors for oneof fields now return default values instead of nil.
+
+ Java Lite
+ * Java lite support is removed from protocol compiler. It will be supported
+ as a protocol compiler plugin in a separate code branch.
+
2016-05-16 version 3.0.0-beta-3 (C++/Java/Python/Ruby/Nano/Objective-C/C#/JavaScript)
General
* Supported Proto3 lite-runtime in C++/Java for mobile platforms.
diff --git a/Makefile.am b/Makefile.am
index 1443b753..a4de1bd3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -51,30 +51,29 @@ pkgconfig_DATA = protobuf.pc protobuf-lite.pc
csharp_EXTRA_DIST= \
csharp/.gitignore \
csharp/CHANGES.txt \
+ csharp/Google.Protobuf.Tools.nuspec \
csharp/README.md \
csharp/build_packages.bat \
csharp/buildall.sh \
csharp/generate_protos.sh \
csharp/keys/Google.Protobuf.public.snk \
+ csharp/keys/Google.Protobuf.snk \
csharp/keys/README.md \
csharp/protos/unittest_issues.proto \
csharp/src/AddressBook/AddPerson.cs \
- csharp/src/AddressBook/AddressBook.csproj \
csharp/src/AddressBook/Addressbook.cs \
+ csharp/src/AddressBook/AddressBook.xproj \
csharp/src/AddressBook/ListPeople.cs \
csharp/src/AddressBook/Program.cs \
- 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/AddressBook/project.json \
csharp/src/Google.Protobuf.Conformance/Conformance.cs \
- csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj \
+ csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.xproj \
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.Conformance/project.json \
+ csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.xproj \
csharp/src/Google.Protobuf.JsonDump/Program.cs \
- csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs \
- csharp/src/Google.Protobuf.JsonDump/app.config \
+ csharp/src/Google.Protobuf.JsonDump/project.json \
csharp/src/Google.Protobuf.Test/ByteStringTest.cs \
csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs \
csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs \
@@ -87,19 +86,18 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf.Test/EqualityTester.cs \
csharp/src/Google.Protobuf.Test/FieldCodecTest.cs \
csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs \
- csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj \
+ csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.xproj \
csharp/src/Google.Protobuf.Test/IssuesTest.cs \
csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs \
csharp/src/Google.Protobuf.Test/JsonParserTest.cs \
csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs \
- csharp/src/Google.Protobuf.Test/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/Reflection/TypeRegistryTest.cs \
csharp/src/Google.Protobuf.Test/SampleEnum.cs \
csharp/src/Google.Protobuf.Test/SampleMessages.cs \
csharp/src/Google.Protobuf.Test/TestCornerCases.cs \
+ csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs \
csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs \
csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs \
csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs \
@@ -108,9 +106,10 @@ csharp_EXTRA_DIST= \
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/FieldMaskTest.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.Test/project.json \
csharp/src/Google.Protobuf.sln \
csharp/src/Google.Protobuf/ByteArray.cs \
csharp/src/Google.Protobuf/ByteString.cs \
@@ -124,8 +123,8 @@ csharp_EXTRA_DIST= \
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/Google.Protobuf.xproj \
+ csharp/src/Google.Protobuf/ICustomDiagnosticMessage.cs \
csharp/src/Google.Protobuf/IDeepCloneable.cs \
csharp/src/Google.Protobuf/IMessage.cs \
csharp/src/Google.Protobuf/InvalidJsonException.cs \
@@ -173,6 +172,7 @@ csharp_EXTRA_DIST= \
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/FieldMaskPartial.cs \
csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs \
csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs \
csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs \
@@ -183,7 +183,7 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs \
csharp/src/Google.Protobuf/WellKnownTypes/WrappersPartial.cs \
csharp/src/Google.Protobuf/WireFormat.cs \
- csharp/src/Google.Protobuf/packages.config \
+ csharp/src/Google.Protobuf/project.json \
csharp/src/packages/repositories.config
java_EXTRA_DIST= \
@@ -206,6 +206,7 @@ java_EXTRA_DIST=
java/core/src/main/java/com/google/protobuf/Descriptors.java \
java/core/src/main/java/com/google/protobuf/DoubleArrayList.java \
java/core/src/main/java/com/google/protobuf/DynamicMessage.java \
+ java/core/src/main/java/com/google/protobuf/ExperimentalApi.java \
java/core/src/main/java/com/google/protobuf/Extension.java \
java/core/src/main/java/com/google/protobuf/ExtensionLite.java \
java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java \
@@ -215,6 +216,7 @@ java_EXTRA_DIST=
java/core/src/main/java/com/google/protobuf/FloatArrayList.java \
java/core/src/main/java/com/google/protobuf/GeneratedMessage.java \
java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java \
+ java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java \
java/core/src/main/java/com/google/protobuf/IntArrayList.java \
java/core/src/main/java/com/google/protobuf/Internal.java \
java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
@@ -240,6 +242,7 @@ java_EXTRA_DIST=
java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java \
java/core/src/main/java/com/google/protobuf/ProtocolStringList.java \
java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java \
+ java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java \
java/core/src/main/java/com/google/protobuf/RopeByteString.java \
java/core/src/main/java/com/google/protobuf/RpcCallback.java \
java/core/src/main/java/com/google/protobuf/RpcChannel.java \
@@ -248,6 +251,7 @@ java_EXTRA_DIST=
java/core/src/main/java/com/google/protobuf/Service.java \
java/core/src/main/java/com/google/protobuf/ServiceException.java \
java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java \
+ java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java \
java/core/src/main/java/com/google/protobuf/SmallSortedMap.java \
java/core/src/main/java/com/google/protobuf/TextFormat.java \
java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java \
@@ -258,6 +262,7 @@ java_EXTRA_DIST=
java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java \
java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java \
java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java \
+ java/core/src/main/java/com/google/protobuf/UnsafeUtil.java \
java/core/src/main/java/com/google/protobuf/Utf8.java \
java/core/src/main/java/com/google/protobuf/WireFormat.java \
java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java \
@@ -297,16 +302,18 @@ java_EXTRA_DIST=
java/core/src/test/java/com/google/protobuf/MessageTest.java \
java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java \
java/core/src/test/java/com/google/protobuf/NioByteStringTest.java \
+ java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java \
java/core/src/test/java/com/google/protobuf/ParserTest.java \
java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java \
- java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java \
+ java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java \
java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java \
java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java \
java/core/src/test/java/com/google/protobuf/ServiceTest.java \
- java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java \
+ java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java \
java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java \
java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java \
java/core/src/test/java/com/google/protobuf/TestUtil.java \
+ java/core/src/test/java/com/google/protobuf/TestUtilLite.java \
java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java \
java/core/src/test/java/com/google/protobuf/TextFormatParseLocationTest.java \
java/core/src/test/java/com/google/protobuf/TextFormatTest.java \
@@ -338,13 +345,17 @@ java_EXTRA_DIST=
java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto \
java/core/src/test/proto/com/google/protobuf/test_custom_options.proto \
java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto \
+ java/lite/generate-sources-build.xml \
+ java/lite/generate-test-sources-build.xml \
java/lite/pom.xml \
java/pom.xml \
java/util/pom.xml \
+ java/util/src/main/java/com/google/protobuf/util/Durations.java \
java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java \
java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java \
java/util/src/main/java/com/google/protobuf/util/JsonFormat.java \
java/util/src/main/java/com/google/protobuf/util/TimeUtil.java \
+ java/util/src/main/java/com/google/protobuf/util/Timestamps.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 \
@@ -463,8 +474,6 @@ objectivec_EXTRA_DIST= \
objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj \
objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata \
objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings \
- objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/FFE465CA-0E74-40E8-9F09-500B66B7DCB2.plist \
- objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/Info.plist \
objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \
objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \
objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj \
@@ -473,6 +482,33 @@ objectivec_EXTRA_DIST= \
objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \
objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \
objectivec/README.md \
+ objectivec/Tests/CocoaPods/OSXCocoaPodsTester/OSXCocoaPodsTester.xcodeproj/project.pbxproj \
+ objectivec/Tests/CocoaPods/OSXCocoaPodsTester/OSXCocoaPodsTester.xcodeproj/project.xcworkspace/contents.xcworkspacedata \
+ objectivec/Tests/CocoaPods/OSXCocoaPodsTester/OSXCocoaPodsTester.xcodeproj/xcshareddata/xcschemes/OSXCocoaPodsTester.xcscheme \
+ objectivec/Tests/CocoaPods/OSXCocoaPodsTester/OSXCocoaPodsTester/AppDelegate.h \
+ objectivec/Tests/CocoaPods/OSXCocoaPodsTester/OSXCocoaPodsTester/AppDelegate.m \
+ objectivec/Tests/CocoaPods/OSXCocoaPodsTester/OSXCocoaPodsTester/Assets.xcassets/AppIcon.appiconset/Contents.json \
+ objectivec/Tests/CocoaPods/OSXCocoaPodsTester/OSXCocoaPodsTester/Base.lproj/MainMenu.xib \
+ objectivec/Tests/CocoaPods/OSXCocoaPodsTester/OSXCocoaPodsTester/Info.plist \
+ objectivec/Tests/CocoaPods/OSXCocoaPodsTester/OSXCocoaPodsTester/main.m \
+ objectivec/Tests/CocoaPods/OSXCocoaPodsTester/Podfile-framework \
+ objectivec/Tests/CocoaPods/OSXCocoaPodsTester/Podfile-static \
+ objectivec/Tests/CocoaPods/README.md \
+ objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-framework \
+ objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-static \
+ objectivec/Tests/CocoaPods/iOSCocoaPodsTester/iOSCocoaPodsTester.xcodeproj/project.pbxproj \
+ objectivec/Tests/CocoaPods/iOSCocoaPodsTester/iOSCocoaPodsTester.xcodeproj/project.xcworkspace/contents.xcworkspacedata \
+ objectivec/Tests/CocoaPods/iOSCocoaPodsTester/iOSCocoaPodsTester.xcodeproj/xcshareddata/xcschemes/iOSCocoaPodsTester.xcscheme \
+ objectivec/Tests/CocoaPods/iOSCocoaPodsTester/iOSCocoaPodsTester/AppDelegate.h \
+ objectivec/Tests/CocoaPods/iOSCocoaPodsTester/iOSCocoaPodsTester/AppDelegate.m \
+ objectivec/Tests/CocoaPods/iOSCocoaPodsTester/iOSCocoaPodsTester/Assets.xcassets/AppIcon.appiconset/Contents.json \
+ objectivec/Tests/CocoaPods/iOSCocoaPodsTester/iOSCocoaPodsTester/Base.lproj/LaunchScreen.storyboard \
+ objectivec/Tests/CocoaPods/iOSCocoaPodsTester/iOSCocoaPodsTester/Base.lproj/Main.storyboard \
+ objectivec/Tests/CocoaPods/iOSCocoaPodsTester/iOSCocoaPodsTester/Info.plist \
+ objectivec/Tests/CocoaPods/iOSCocoaPodsTester/iOSCocoaPodsTester/ViewController.h \
+ objectivec/Tests/CocoaPods/iOSCocoaPodsTester/iOSCocoaPodsTester/ViewController.m \
+ objectivec/Tests/CocoaPods/iOSCocoaPodsTester/iOSCocoaPodsTester/main.m \
+ objectivec/Tests/CocoaPods/run_tests.sh \
objectivec/Tests/golden_message \
objectivec/Tests/golden_packed_fields_message \
objectivec/Tests/GPBARCUnittestProtos.m \
@@ -498,6 +534,7 @@ objectivec_EXTRA_DIST= \
objectivec/Tests/GPBTestUtilities.h \
objectivec/Tests/GPBTestUtilities.m \
objectivec/Tests/GPBUnittestProtos.m \
+ objectivec/Tests/GPBUnittestProtos2.m \
objectivec/Tests/GPBUnknownFieldSetTest.m \
objectivec/Tests/GPBUtilitiesTests.m \
objectivec/Tests/GPBWellKnownTypesTest.m \
@@ -519,6 +556,13 @@ objectivec_EXTRA_DIST= \
objectivec/Tests/text_format_map_unittest_data.txt \
objectivec/Tests/text_format_unittest_data.txt \
objectivec/Tests/unittest_cycle.proto \
+ objectivec/Tests/unittest_extension_chain_a.proto \
+ objectivec/Tests/unittest_extension_chain_b.proto \
+ objectivec/Tests/unittest_extension_chain_c.proto \
+ objectivec/Tests/unittest_extension_chain_d.proto \
+ objectivec/Tests/unittest_extension_chain_e.proto \
+ objectivec/Tests/unittest_extension_chain_f.proto \
+ objectivec/Tests/unittest_extension_chain_g.proto \
objectivec/Tests/unittest_objc.proto \
objectivec/Tests/unittest_objc_startup.proto \
objectivec/Tests/unittest_runtime_proto2.proto \
@@ -551,6 +595,7 @@ python_EXTRA_DIST= \
python/google/protobuf/internal/enum_type_wrapper.py \
python/google/protobuf/internal/factory_test1.proto \
python/google/protobuf/internal/factory_test2.proto \
+ python/google/protobuf/internal/file_options_test.proto \
python/google/protobuf/internal/generator_test.py \
python/google/protobuf/internal/import_test_package/__init__.py \
python/google/protobuf/internal/import_test_package/inner.proto \
@@ -603,6 +648,7 @@ python_EXTRA_DIST= \
python/google/protobuf/pyext/map_container.h \
python/google/protobuf/pyext/message.cc \
python/google/protobuf/pyext/message.h \
+ python/google/protobuf/pyext/message_module.cc \
python/google/protobuf/pyext/proto2_api_test.proto \
python/google/protobuf/pyext/python.proto \
python/google/protobuf/pyext/python_protobuf.h \
@@ -618,6 +664,7 @@ python_EXTRA_DIST= \
python/google/protobuf/text_encoding.py \
python/google/protobuf/text_format.py \
python/mox.py \
+ python/setup.cfg \
python/setup.py \
python/stubout.py \
python/tox.ini \
@@ -643,6 +690,7 @@ ruby_EXTRA_DIST= \
ruby/google-protobuf.gemspec \
ruby/lib/google/protobuf/message_exts.rb \
ruby/lib/google/protobuf/repeated_field.rb \
+ ruby/lib/google/protobuf/well_known_types.rb \
ruby/lib/google/protobuf.rb \
ruby/pom.xml \
ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java \
@@ -667,42 +715,53 @@ ruby_EXTRA_DIST= \
ruby/tests/repeated_field_test.rb \
ruby/tests/stress.rb \
ruby/tests/generated_code.proto \
+ ruby/tests/test_import.proto \
ruby/tests/generated_code_test.rb \
+ ruby/tests/well_known_types_test.rb \
ruby/travis-test.sh
-js_EXTRA_DIST= \
- js/README.md \
- js/binary/arith.js \
- js/binary/arith_test.js \
- js/binary/constants.js \
- js/binary/decoder.js \
- js/binary/decoder_test.js \
- js/binary/encoder.js \
- js/binary/proto_test.js \
- js/binary/reader.js \
- js/binary/reader_test.js \
- js/binary/utils.js \
- js/binary/utils_test.js \
- js/binary/writer.js \
- js/binary/writer_test.js \
- js/data.proto \
- js/debug.js \
- js/debug_test.js \
- js/gulpfile.js \
- js/jasmine.json \
- js/message.js \
- js/message_test.js \
- js/node_loader.js \
- js/package.json \
- js/proto3_test.js \
- js/proto3_test.proto \
- js/test.proto \
- js/test2.proto \
- js/test3.proto \
- js/test4.proto \
- js/test5.proto \
- js/test_bootstrap.js \
- js/testbinary.proto \
+js_EXTRA_DIST= \
+ js/README.md \
+ js/binary/arith.js \
+ js/binary/arith_test.js \
+ js/binary/constants.js \
+ js/binary/decoder.js \
+ js/binary/decoder_test.js \
+ js/binary/encoder.js \
+ js/binary/proto_test.js \
+ js/binary/reader.js \
+ js/binary/reader_test.js \
+ js/binary/utils.js \
+ js/binary/utils_test.js \
+ js/binary/writer.js \
+ js/binary/writer_test.js \
+ js/commonjs/export.js \
+ js/commonjs/export_asserts.js \
+ js/commonjs/export_testdeps.js \
+ js/commonjs/import_test.js \
+ js/commonjs/jasmine.json \
+ js/commonjs/rewrite_tests_for_commonjs.js \
+ js/commonjs/test6/test6.proto \
+ js/commonjs/test7/test7.proto \
+ js/data.proto \
+ js/debug.js \
+ js/debug_test.js \
+ js/gulpfile.js \
+ js/jasmine.json \
+ js/map.js \
+ js/message.js \
+ js/message_test.js \
+ js/node_loader.js \
+ js/package.json \
+ js/proto3_test.js \
+ js/proto3_test.proto \
+ js/test.proto \
+ js/test2.proto \
+ js/test3.proto \
+ js/test4.proto \
+ js/test5.proto \
+ js/test_bootstrap.js \
+ js/testbinary.proto \
js/testempty.proto
all_EXTRA_DIST=$(csharp_EXTRA_DIST) $(java_EXTRA_DIST) $(javanano_EXTRA_DIST) $(objectivec_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST) $(js_EXTRA_DIST)
@@ -720,6 +779,7 @@ EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \
WORKSPACE \
cmake/CMakeLists.txt \
cmake/README.md \
+ cmake/examples.cmake \
cmake/extract_includes.bat.in \
cmake/install.cmake \
cmake/libprotobuf.cmake \
@@ -728,11 +788,13 @@ EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \
cmake/protobuf-config-version.cmake.in \
cmake/protobuf-config.cmake.in \
cmake/protobuf-module.cmake.in \
+ cmake/protobuf-options.cmake \
cmake/protoc.cmake \
cmake/tests.cmake \
editors/README.txt \
editors/proto.vim \
editors/protobuf-mode.el \
+ examples/CMakeLists.txt \
examples/README.txt \
examples/Makefile \
examples/addressbook.proto \
@@ -742,6 +804,7 @@ EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \
examples/list_people.cc \
examples/list_people.go \
examples/AddPerson.java \
+ examples/CMakeLists.txt \
examples/ListPeople.java \
examples/add_person.py \
examples/list_people.py \
diff --git a/Protobuf.podspec b/Protobuf.podspec
index 2523076a..72e6dd0a 100644
--- a/Protobuf.podspec
+++ b/Protobuf.podspec
@@ -5,7 +5,7 @@
# dependent projects use the :git notation to refer to the library.
Pod::Spec.new do |s|
s.name = 'Protobuf'
- s.version = '3.0.0-beta-3'
+ s.version = '3.0.0'
s.summary = 'Protocol Buffers v.3 runtime library for Objective-C.'
s.homepage = 'https://github.com/google/protobuf'
s.license = 'New BSD'
@@ -36,5 +36,6 @@ Pod::Spec.new do |s|
s.ios.deployment_target = '7.1'
s.osx.deployment_target = '10.9'
+ s.watchos.deployment_target = '2.0'
s.requires_arc = false
end
diff --git a/README.md b/README.md
index ba9c589d..67be3e9b 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
Protocol Buffers - Google's data interchange format
===================================================
-[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf)
+[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf) [![Build Status](https://grpc-testing.appspot.com/buildStatus/icon?job=protobuf_branch)](https://grpc-testing.appspot.com/job/protobuf_branch)
Copyright 2008 Google Inc.
diff --git a/WORKSPACE b/WORKSPACE
index 065dc819..df919ad1 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,15 +1,15 @@
-new_http_archive(
- name = "gmock_archive",
- url = "https://googlemock.googlecode.com/files/gmock-1.7.0.zip",
- sha256 = "26fcbb5925b74ad5fc8c26b0495dfc96353f4d553492eb97e85a8a6d2f43095b",
+new_git_repository(
+ name = "googletest",
build_file = "gmock.BUILD",
+ remote = "https://github.com/google/googletest",
+ tag = "release-1.8.0",
)
new_http_archive(
name = "six_archive",
- url = "https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz#md5=34eed507548117b2ab523ab14b2f8b55",
- sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a",
build_file = "six.BUILD",
+ sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a",
+ url = "https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz#md5=34eed507548117b2ab523ab14b2f8b55",
)
bind(
@@ -19,12 +19,12 @@ bind(
bind(
name = "gtest",
- actual = "@gmock_archive//:gtest",
+ actual = "@googletest//:gtest",
)
bind(
name = "gtest_main",
- actual = "@gmock_archive//:gtest_main",
+ actual = "@googletest//:gtest_main",
)
bind(
@@ -33,8 +33,8 @@ bind(
)
maven_jar(
- name = "guava_maven",
- artifact = "com.google.guava:guava:18.0",
+ name = "guava_maven",
+ artifact = "com.google.guava:guava:18.0",
)
bind(
@@ -43,8 +43,8 @@ bind(
)
maven_jar(
- name = "gson_maven",
- artifact = "com.google.code.gson:gson:2.3",
+ name = "gson_maven",
+ artifact = "com.google.code.gson:gson:2.3",
)
bind(
diff --git a/appveyor.bat b/appveyor.bat
index 9a46b928..916f4434 100644
--- a/appveyor.bat
+++ b/appveyor.bat
@@ -10,7 +10,7 @@ goto :error
echo Building C++
mkdir build_msvc
cd build_msvc
-cmake -G "%generator%" -Dprotobuf_BUILD_SHARED_LIBS=%BUILD_DLL% ../cmake
+cmake -G "%generator%" -Dprotobuf_BUILD_SHARED_LIBS=%BUILD_DLL% -Dprotobuf_UNICODE=%UNICODE% ../cmake
msbuild protobuf.sln /p:Platform=%vcplatform% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || goto error
cd %configuration%
tests.exe || goto error
@@ -19,9 +19,12 @@ goto :EOF
:build_csharp
echo Building C#
cd csharp\src
-nuget restore
-msbuild Google.Protobuf.sln /p:Platform="Any CPU" /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || goto error
-nunit-console Google.Protobuf.Test\bin\%configuration%\Google.Protobuf.Test.dll || goto error
+dotnet restore
+dotnet build -c %configuration% Google.Protobuf Google.Protobuf.Test Google.Protobuf.Conformance || goto error
+
+echo Testing C#
+dotnet test -c %configuration% Google.Protobuf.Test || goto error
+
goto :EOF
:error
diff --git a/appveyor.yml b/appveyor.yml
index c84ecae2..20fc8ade 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -11,13 +11,26 @@ environment:
matrix:
- language: cpp
BUILD_DLL: ON
+ UNICODE: ON
- language: csharp
+# Our build scripts run tests automatically; we don't want AppVeyor
+# to try to detect them itself.
+test: off
+
install:
- - ps: Start-FileDownload https://googlemock.googlecode.com/files/gmock-1.7.0.zip
- - 7z x gmock-1.7.0.zip
- - rename gmock-1.7.0 gmock
+ - ps: Start-FileDownload https://github.com/google/googlemock/archive/release-1.7.0.zip
+ - 7z x release-1.7.0.zip
+ - del /Q release-1.7.0.zip
+ - rename googlemock-release-1.7.0 gmock
+ - ps: Start-FileDownload https://github.com/google/googletest/archive/release-1.7.0.zip
+ - 7z x release-1.7.0.zip
+ - del /Q release-1.7.0.zip
+ - rename googletest-release-1.7.0 gtest
+ - move gtest gmock
+ - ps: Start-FileDownload https://go.microsoft.com/fwlink/?LinkID=809122 -FileName dotnetsdk.exe
+ - dotnetsdk.exe /install /quiet /norestart
before_build:
- if %platform%==Win32 set generator=Visual Studio 12
diff --git a/autogen.sh b/autogen.sh
index 5b4c29f8..9f266425 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -31,10 +31,15 @@ fi
# directory is set up as an SVN external.
if test ! -e gmock; then
echo "Google Mock not present. Fetching gmock-1.7.0 from the web..."
- curl $curlopts -O https://googlemock.googlecode.com/files/gmock-1.7.0.zip
- unzip -q gmock-1.7.0.zip
- rm gmock-1.7.0.zip
- mv gmock-1.7.0 gmock
+ curl $curlopts -L -O https://github.com/google/googlemock/archive/release-1.7.0.zip
+ unzip -q release-1.7.0.zip
+ rm release-1.7.0.zip
+ mv googlemock-release-1.7.0 gmock
+
+ curl $curlopts -L -O https://github.com/google/googletest/archive/release-1.7.0.zip
+ unzip -q release-1.7.0.zip
+ rm release-1.7.0.zip
+ mv googletest-release-1.7.0 gmock/gtest
fi
set -ex
diff --git a/benchmarks/readme.txt b/benchmarks/readme.txt
index 2c836d0a..b08b8bc0 100644
--- a/benchmarks/readme.txt
+++ b/benchmarks/readme.txt
@@ -22,29 +22,25 @@ Running a benchmark (Java)
$ javac -d tmp -cp protobuf.jar ProtoBench.java
3) Generate code for the relevant benchmark protocol buffer, e.g.
- $ protoc --java_out=tmp google_size.proto google_speed.proto
+ $ protoc --java_out=tmp google_size.proto
4) Build the generated code, e.g.
- $ cd tmp
- $ javac -d . -cp ../protobuf.jar benchmarks/*.java
+ $ javac -d tmp -cp protobuf.jar tmp/benchmarks/*.java
5) Run the test. Arguments are given in pairs - the first argument
is the descriptor type; the second is the filename. For example:
- $ java -cp .;../protobuf.jar com.google.protocolbuffers.ProtoBench
- benchmarks.GoogleSize$SizeMessage1 ../google_message1.dat
- benchmarks.GoogleSpeed$SpeedMessage1 ../google_message1.dat
- benchmarks.GoogleSize$SizeMessage2 ../google_message2.dat
- benchmarks.GoogleSpeed$SpeedMessage2 ../google_message2.dat
+ $ java -cp tmp:protobuf.jar com.google.protocolbuffers.ProtoBench \
+ 'benchmarks.GoogleSize$SizeMessage1' google_message1.dat \
+ 'benchmarks.GoogleSize$SizeMessage2' google_message2.dat
-6) Wait! Each test runs for around 30 seconds, and there are 6 tests
+6) Wait! Each test runs for around 30 seconds, and there are 8 tests
per class/data combination. The above command would therefore take
- about 12 minutes to run.
+ about 8 minutes to run.
Benchmarks available
--------------------
From Google:
-google_size.proto and google_speed.proto, messages
-google_message1.dat and google_message2.dat. The proto files are
-equivalent, but optimized differently.
+google_size.proto,
+messages google_message1.dat and google_message2.dat.
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index 07b176d9..df3b2012 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -86,6 +86,7 @@ if (CMAKE_USE_PTHREADS_INIT)
add_definitions(-DHAVE_PTHREAD)
endif (CMAKE_USE_PTHREADS_INIT)
+set(_protobuf_FIND_ZLIB)
if (protobuf_WITH_ZLIB)
find_package(ZLIB)
if (ZLIB_FOUND)
@@ -96,6 +97,7 @@ if (protobuf_WITH_ZLIB)
# Using imported target if exists
if (TARGET ZLIB::ZLIB)
set(ZLIB_LIBRARIES ZLIB::ZLIB)
+ set(_protobuf_FIND_ZLIB "if(NOT ZLIB_FOUND)\n find_package(ZLIB)\nendif()")
endif (TARGET ZLIB::ZLIB)
else (ZLIB_FOUND)
set(HAVE_ZLIB 0)
@@ -157,6 +159,10 @@ else (MSVC)
set(LIB_PREFIX)
endif (MSVC)
+if (protobuf_UNICODE)
+ add_definitions(-DUNICODE -D_UNICODE)
+endif (protobuf_UNICODE)
+
include(libprotobuf-lite.cmake)
include(libprotobuf.cmake)
include(libprotoc.cmake)
diff --git a/cmake/examples.cmake b/cmake/examples.cmake
index 0a651051..e5cad63f 100644
--- a/cmake/examples.cmake
+++ b/cmake/examples.cmake
@@ -1,57 +1,57 @@
-if(protobuf_VERBOSE)
- message(STATUS "Protocol Buffers Examples Configuring...")
-endif()
-
-get_filename_component(examples_dir "../examples" ABSOLUTE)
-
-if(protobuf_VERBOSE)
- message(STATUS "Protocol Buffers Examples Configuring done")
-endif()
-include(ExternalProject)
-
-# Internal utility function: Create a custom target representing a build of examples with custom options.
-function(add_examples_build NAME)
-
- ExternalProject_Add(${NAME}
- PREFIX ${NAME}
- SOURCE_DIR "${examples_dir}"
- BINARY_DIR ${NAME}
- STAMP_DIR ${NAME}/logs
- INSTALL_COMMAND "" #Skip
- LOG_CONFIGURE 1
- CMAKE_CACHE_ARGS "-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
- "-Dprotobuf_VERBOSE:BOOL=${protobuf_VERBOSE}"
- ${ARGN}
- )
- set_property(TARGET ${NAME} PROPERTY FOLDER "Examples")
- set_property(TARGET ${NAME} PROPERTY EXCLUDE_FROM_ALL TRUE)
-endfunction()
-
-# Add examples as an external project.
-# sub_directory cannot be used because the find_package(protobuf) call would cause failures with redefined targets.
-add_examples_build(examples "-Dprotobuf_DIR:PATH=${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}")
-add_dependencies(examples libprotobuf protoc)
-
-option(protobuf_BUILD_EXAMPLES_MULTITEST "Build Examples in multiple configurations. Useful for testing." OFF)
-mark_as_advanced(protobuf_BUILD_EXAMPLES_MULTITEST)
-if(protobuf_BUILD_EXAMPLES_MULTITEST)
- set_property(GLOBAL PROPERTY USE_FOLDERS ON)
-
- #Build using the legacy compatibility module.
- add_examples_build(examples-legacy
- "-Dprotobuf_DIR:PATH=${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}"
- "-Dprotobuf_MODULE_COMPATIBLE:BOOL=TRUE"
- )
- add_dependencies(examples-legacy libprotobuf protoc)
-
- #Build using the installed library.
- add_examples_build(examples-installed
- "-Dprotobuf_DIR:PATH=${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}"
- )
-
- #Build using the installed library in legacy compatibility mode.
- add_examples_build(examples-installed-legacy
- "-Dprotobuf_DIR:PATH=${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}"
- "-Dprotobuf_MODULE_COMPATIBLE:BOOL=TRUE"
- )
-endif()
+if(protobuf_VERBOSE)
+ message(STATUS "Protocol Buffers Examples Configuring...")
+endif()
+
+get_filename_component(examples_dir "../examples" ABSOLUTE)
+
+if(protobuf_VERBOSE)
+ message(STATUS "Protocol Buffers Examples Configuring done")
+endif()
+include(ExternalProject)
+
+# Internal utility function: Create a custom target representing a build of examples with custom options.
+function(add_examples_build NAME)
+
+ ExternalProject_Add(${NAME}
+ PREFIX ${NAME}
+ SOURCE_DIR "${examples_dir}"
+ BINARY_DIR ${NAME}
+ STAMP_DIR ${NAME}/logs
+ INSTALL_COMMAND "" #Skip
+ LOG_CONFIGURE 1
+ CMAKE_CACHE_ARGS "-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
+ "-Dprotobuf_VERBOSE:BOOL=${protobuf_VERBOSE}"
+ ${ARGN}
+ )
+ set_property(TARGET ${NAME} PROPERTY FOLDER "Examples")
+ set_property(TARGET ${NAME} PROPERTY EXCLUDE_FROM_ALL TRUE)
+endfunction()
+
+# Add examples as an external project.
+# sub_directory cannot be used because the find_package(protobuf) call would cause failures with redefined targets.
+add_examples_build(examples "-Dprotobuf_DIR:PATH=${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}")
+add_dependencies(examples libprotobuf protoc)
+
+option(protobuf_BUILD_EXAMPLES_MULTITEST "Build Examples in multiple configurations. Useful for testing." OFF)
+mark_as_advanced(protobuf_BUILD_EXAMPLES_MULTITEST)
+if(protobuf_BUILD_EXAMPLES_MULTITEST)
+ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+
+ #Build using the legacy compatibility module.
+ add_examples_build(examples-legacy
+ "-Dprotobuf_DIR:PATH=${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}"
+ "-Dprotobuf_MODULE_COMPATIBLE:BOOL=TRUE"
+ )
+ add_dependencies(examples-legacy libprotobuf protoc)
+
+ #Build using the installed library.
+ add_examples_build(examples-installed
+ "-Dprotobuf_DIR:PATH=${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}"
+ )
+
+ #Build using the installed library in legacy compatibility mode.
+ add_examples_build(examples-installed-legacy
+ "-Dprotobuf_DIR:PATH=${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}"
+ "-Dprotobuf_MODULE_COMPATIBLE:BOOL=TRUE"
+ )
+endif()
diff --git a/cmake/extract_includes.bat.in b/cmake/extract_includes.bat.in
index c76973c9..9edafca8 100644
--- a/cmake/extract_includes.bat.in
+++ b/cmake/extract_includes.bat.in
@@ -69,7 +69,6 @@ copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\metadata.h include\goo
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection.h include\google\protobuf\reflection.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection_ops.h include\google\protobuf\reflection_ops.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_field.h include\google\protobuf\repeated_field.h
-copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_field_reflection.h include\google\protobuf\repeated_field_reflection.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\service.h include\google\protobuf\service.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\source_context.pb.h include\google\protobuf\source_context.pb.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\struct.pb.h include\google\protobuf\struct.pb.h
diff --git a/cmake/install.cmake b/cmake/install.cmake
index 94ef2198..73e31984 100644
--- a/cmake/install.cmake
+++ b/cmake/install.cmake
@@ -110,7 +110,7 @@ install(EXPORT protobuf-targets
NAMESPACE protobuf::
COMPONENT protobuf-export)
-install(DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}/
+install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}/
DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
COMPONENT protobuf-export
PATTERN protobuf-targets.cmake EXCLUDE
diff --git a/cmake/libprotobuf.cmake b/cmake/libprotobuf.cmake
index 8930c1ca..26e1f356 100644
--- a/cmake/libprotobuf.cmake
+++ b/cmake/libprotobuf.cmake
@@ -56,7 +56,10 @@ set(libprotobuf_files
add_library(libprotobuf ${protobuf_SHARED_OR_STATIC}
${libprotobuf_lite_files} ${libprotobuf_files})
-target_link_libraries(libprotobuf ${CMAKE_THREAD_LIBS_INIT} ${ZLIB_LIBRARIES})
+target_link_libraries(libprotobuf ${CMAKE_THREAD_LIBS_INIT})
+if(protobuf_WITH_ZLIB)
+ target_link_libraries(libprotobuf ${ZLIB_LIBRARIES})
+endif()
target_include_directories(libprotobuf PUBLIC ${protobuf_source_dir}/src)
if(MSVC AND protobuf_BUILD_SHARED_LIBS)
target_compile_definitions(libprotobuf
diff --git a/cmake/protobuf-config-version.cmake.in b/cmake/protobuf-config-version.cmake.in
index 3b8ced2d..0036c9ef 100644
--- a/cmake/protobuf-config-version.cmake.in
+++ b/cmake/protobuf-config-version.cmake.in
@@ -3,7 +3,7 @@ set(${PACKAGE_FIND_NAME}_VERSION_PRERELEASE "@protobuf_VERSION_PRERELEASE@" PARE
# Prerelease versions cannot be passed in directly via the find_package command,
# so we allow users to specify it in a variable
-if(NOT DEFINED "${${PACKAGE_FIND_NAME}_FIND_VERSION_PRERELEASE}")
+if(NOT DEFINED "${PACKAGE_FIND_NAME}_FIND_VERSION_PRERELEASE")
set("${${PACKAGE_FIND_NAME}_FIND_VERSION_PRERELEASE}" "")
else()
set(PACKAGE_FIND_VERSION ${PACKAGE_FIND_VERSION}-${${PACKAGE_FIND_NAME}_FIND_VERSION_PRERELEASE})
diff --git a/cmake/protobuf-config.cmake.in b/cmake/protobuf-config.cmake.in
index 37315510..a044fe5c 100644
--- a/cmake/protobuf-config.cmake.in
+++ b/cmake/protobuf-config.cmake.in
@@ -1,6 +1,9 @@
# User options
include("${CMAKE_CURRENT_LIST_DIR}/protobuf-options.cmake")
+# Depend packages
+@_protobuf_FIND_ZLIB@
+
# Imported targets
include("${CMAKE_CURRENT_LIST_DIR}/protobuf-targets.cmake")
diff --git a/cmake/protobuf-module.cmake.in b/cmake/protobuf-module.cmake.in
index 6e0bcf90..614e4c04 100644
--- a/cmake/protobuf-module.cmake.in
+++ b/cmake/protobuf-module.cmake.in
@@ -147,7 +147,6 @@ function(_protobuf_find_libraries name filename)
LOCATION_RELEASE)
get_target_property(${name}_LIBRARY_DEBUG protobuf::lib${filename}
LOCATION_DEBUG)
- endif()
select_library_configurations(${name})
set(${name}_LIBRARY ${${name}_LIBRARY} PARENT_SCOPE)
diff --git a/cmake/protobuf-options.cmake b/cmake/protobuf-options.cmake
index 99c85ebe..47fb1582 100644
--- a/cmake/protobuf-options.cmake
+++ b/cmake/protobuf-options.cmake
@@ -1,7 +1,7 @@
-# Verbose output
-option(protobuf_VERBOSE "Enable for verbose output" OFF)
-mark_as_advanced(protobuf_VERBOSE)
-
-# FindProtobuf module compatibel
-option(protobuf_MODULE_COMPATIBLE "CMake build-in FindProtobuf.cmake module compatible" OFF)
-mark_as_advanced(protobuf_MODULE_COMPATIBLE)
+# Verbose output
+option(protobuf_VERBOSE "Enable for verbose output" OFF)
+mark_as_advanced(protobuf_VERBOSE)
+
+# FindProtobuf module compatibel
+option(protobuf_MODULE_COMPATIBLE "CMake build-in FindProtobuf.cmake module compatible" OFF)
+mark_as_advanced(protobuf_MODULE_COMPATIBLE)
diff --git a/configure.ac b/configure.ac
index d858e177..41887997 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,7 +17,7 @@ AC_PREREQ(2.59)
# In the SVN trunk, the version should always be the next anticipated release
# version with the "-pre" suffix. (We used to use "-SNAPSHOT" but this pushed
# the size of one file name in the dist tarfile over the 99-char limit.)
-AC_INIT([Protocol Buffers],[3.0.0-beta-3],[protobuf@googlegroups.com],[protobuf])
+AC_INIT([Protocol Buffers],[3.0.0],[protobuf@googlegroups.com],[protobuf])
AM_MAINTAINER_MODE([enable])
diff --git a/conformance/Makefile.am b/conformance/Makefile.am
index 5538cc75..28ac3c8a 100644
--- a/conformance/Makefile.am
+++ b/conformance/Makefile.am
@@ -20,7 +20,7 @@ other_language_protoc_outputs = \
conformance_pb2.py \
Conformance.pbobjc.h \
Conformance.pbobjc.m \
- conformance.rb \
+ conformance_pb.rb \
com/google/protobuf/Any.java \
com/google/protobuf/AnyOrBuilder.java \
com/google/protobuf/AnyProto.java \
@@ -84,47 +84,47 @@ other_language_protoc_outputs = \
google/protobuf/wrappers.pb.cc \
google/protobuf/wrappers.pb.h \
google/protobuf/wrappers.rb \
- google/protobuf/wrappers_pb2.py \
- lite/com/google/protobuf/Any.java \
- lite/com/google/protobuf/AnyOrBuilder.java \
- lite/com/google/protobuf/AnyProto.java \
- lite/com/google/protobuf/BoolValue.java \
- lite/com/google/protobuf/BoolValueOrBuilder.java \
- lite/com/google/protobuf/BytesValue.java \
- lite/com/google/protobuf/BytesValueOrBuilder.java \
- lite/com/google/protobuf/conformance/Conformance.java \
- lite/com/google/protobuf/DoubleValue.java \
- lite/com/google/protobuf/DoubleValueOrBuilder.java \
- lite/com/google/protobuf/Duration.java \
- lite/com/google/protobuf/DurationOrBuilder.java \
- lite/com/google/protobuf/DurationProto.java \
- lite/com/google/protobuf/FieldMask.java \
- lite/com/google/protobuf/FieldMaskOrBuilder.java \
- lite/com/google/protobuf/FieldMaskProto.java \
- lite/com/google/protobuf/FloatValue.java \
- lite/com/google/protobuf/FloatValueOrBuilder.java \
- lite/com/google/protobuf/Int32Value.java \
- lite/com/google/protobuf/Int32ValueOrBuilder.java \
- lite/com/google/protobuf/Int64Value.java \
- lite/com/google/protobuf/Int64ValueOrBuilder.java \
- lite/com/google/protobuf/ListValue.java \
- lite/com/google/protobuf/ListValueOrBuilder.java \
- lite/com/google/protobuf/NullValue.java \
- lite/com/google/protobuf/StringValue.java \
- lite/com/google/protobuf/StringValueOrBuilder.java \
- lite/com/google/protobuf/Struct.java \
- lite/com/google/protobuf/StructOrBuilder.java \
- lite/com/google/protobuf/StructProto.java \
- lite/com/google/protobuf/Timestamp.java \
- lite/com/google/protobuf/TimestampOrBuilder.java \
- lite/com/google/protobuf/TimestampProto.java \
- lite/com/google/protobuf/UInt32Value.java \
- lite/com/google/protobuf/UInt32ValueOrBuilder.java \
- lite/com/google/protobuf/UInt64Value.java \
- lite/com/google/protobuf/UInt64ValueOrBuilder.java \
- lite/com/google/protobuf/Value.java \
- lite/com/google/protobuf/ValueOrBuilder.java \
- lite/com/google/protobuf/WrappersProto.java
+ google/protobuf/wrappers_pb2.py
+ # lite/com/google/protobuf/Any.java \
+ # lite/com/google/protobuf/AnyOrBuilder.java \
+ # lite/com/google/protobuf/AnyProto.java \
+ # lite/com/google/protobuf/BoolValue.java \
+ # lite/com/google/protobuf/BoolValueOrBuilder.java \
+ # lite/com/google/protobuf/BytesValue.java \
+ # lite/com/google/protobuf/BytesValueOrBuilder.java \
+ # lite/com/google/protobuf/conformance/Conformance.java \
+ # lite/com/google/protobuf/DoubleValue.java \
+ # lite/com/google/protobuf/DoubleValueOrBuilder.java \
+ # lite/com/google/protobuf/Duration.java \
+ # lite/com/google/protobuf/DurationOrBuilder.java \
+ # lite/com/google/protobuf/DurationProto.java \
+ # lite/com/google/protobuf/FieldMask.java \
+ # lite/com/google/protobuf/FieldMaskOrBuilder.java \
+ # lite/com/google/protobuf/FieldMaskProto.java \
+ # lite/com/google/protobuf/FloatValue.java \
+ # lite/com/google/protobuf/FloatValueOrBuilder.java \
+ # lite/com/google/protobuf/Int32Value.java \
+ # lite/com/google/protobuf/Int32ValueOrBuilder.java \
+ # lite/com/google/protobuf/Int64Value.java \
+ # lite/com/google/protobuf/Int64ValueOrBuilder.java \
+ # lite/com/google/protobuf/ListValue.java \
+ # lite/com/google/protobuf/ListValueOrBuilder.java \
+ # lite/com/google/protobuf/NullValue.java \
+ # lite/com/google/protobuf/StringValue.java \
+ # lite/com/google/protobuf/StringValueOrBuilder.java \
+ # lite/com/google/protobuf/Struct.java \
+ # lite/com/google/protobuf/StructOrBuilder.java \
+ # lite/com/google/protobuf/StructProto.java \
+ # lite/com/google/protobuf/Timestamp.java \
+ # lite/com/google/protobuf/TimestampOrBuilder.java \
+ # lite/com/google/protobuf/TimestampProto.java \
+ # lite/com/google/protobuf/UInt32Value.java \
+ # lite/com/google/protobuf/UInt32ValueOrBuilder.java \
+ # lite/com/google/protobuf/UInt64Value.java \
+ # lite/com/google/protobuf/UInt64ValueOrBuilder.java \
+ # lite/com/google/protobuf/Value.java \
+ # lite/com/google/protobuf/ValueOrBuilder.java \
+ # lite/com/google/protobuf/WrappersProto.java
bin_PROGRAMS = conformance-test-runner conformance-cpp
@@ -192,7 +192,7 @@ if USE_EXTERNAL_PROTOC
protoc_middleman: $(conformance_protoc_inputs) $(well_known_type_protoc_inputs)
$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. --python_out=. $(conformance_protoc_inputs)
$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --python_out=. $(well_known_type_protoc_inputs)
- $(PROTOC) -I$(srcdir) -I$(top_srcdir) --java_out=lite:lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs)
+ ## $(PROTOC) -I$(srcdir) -I$(top_srcdir) --java_out=lite:lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs)
touch protoc_middleman
else
@@ -203,8 +203,8 @@ else
protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(conformance_protoc_inputs) $(well_known_type_protoc_inputs)
oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --objc_out=$$oldpwd --python_out=$$oldpwd $(conformance_protoc_inputs) )
oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --python_out=$$oldpwd $(well_known_type_protoc_inputs) )
- @mkdir -p lite
- oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --java_out=lite:$$oldpwd/lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) )
+ ## @mkdir -p lite
+ ## oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --java_out=lite:$$oldpwd/lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) )
touch protoc_middleman
endif
@@ -246,7 +246,7 @@ conformance-java-lite: javac_middleman_lite
conformance-csharp: $(other_language_protoc_outputs)
@echo "Writing shortcut script conformance-csharp..."
@echo '#! /bin/sh' > conformance-csharp
- @echo 'mono ../csharp/src/Google.Protobuf.Conformance/bin/Release/Google.Protobuf.Conformance.exe "$$@"' >> conformance-csharp
+ @echo 'dotnet ../csharp/src/Google.Protobuf.Conformance/bin/Release/netcoreapp1.0/Google.Protobuf.Conformance.dll "$$@"' >> conformance-csharp
@chmod +x conformance-csharp
# Targets for actually running tests.
diff --git a/conformance/conformance.proto b/conformance/conformance.proto
index fc96074a..95a8fd13 100644
--- a/conformance/conformance.proto
+++ b/conformance/conformance.proto
@@ -210,6 +210,11 @@ message TestAllTypes {
NestedMessage oneof_nested_message = 112;
string oneof_string = 113;
bytes oneof_bytes = 114;
+ bool oneof_bool = 115;
+ uint64 oneof_uint64 = 116;
+ float oneof_float = 117;
+ double oneof_double = 118;
+ NestedEnum oneof_enum = 119;
}
// Well-known types
@@ -248,6 +253,7 @@ message TestAllTypes {
repeated google.protobuf.Value repeated_value = 316;
// Test field-name-to-JSON-name convention.
+ // (protobuf says names can be any valid C/C++ identifier.)
int32 fieldname1 = 401;
int32 field_name2 = 402;
int32 _field_name3 = 403;
@@ -260,6 +266,12 @@ message TestAllTypes {
int32 Field_Name10 = 410;
int32 FIELD_NAME11 = 411;
int32 FIELD_name12 = 412;
+ int32 __field_name13 = 413;
+ int32 __Field_name14 = 414;
+ int32 field__name15 = 415;
+ int32 field__Name16 = 416;
+ int32 field_name17__ = 417;
+ int32 Field_name18__ = 418;
}
message ForeignMessage {
diff --git a/conformance/conformance_ruby.rb b/conformance/conformance_ruby.rb
index c716facd..aa572144 100755
--- a/conformance/conformance_ruby.rb
+++ b/conformance/conformance_ruby.rb
@@ -30,7 +30,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.
-require 'conformance'
+require 'conformance_pb'
$test_count = 0
$verbose = false
diff --git a/conformance/conformance_test.cc b/conformance/conformance_test.cc
index 59a61e51..fb963f68 100644
--- a/conformance/conformance_test.cc
+++ b/conformance/conformance_test.cc
@@ -272,11 +272,16 @@ void ConformanceTestSuite::RunValidInputTest(
TestAllTypes test_message;
switch (response.result_case()) {
+ case ConformanceResponse::RESULT_NOT_SET:
+ ReportFailure(test_name, request, response,
+ "Response didn't have any field in the Response.");
+ return;
+
case ConformanceResponse::kParseError:
case ConformanceResponse::kRuntimeError:
case ConformanceResponse::kSerializeError:
ReportFailure(test_name, request, response,
- "Failed to parse JSON input or produce JSON output.");
+ "Failed to parse input or produce output.");
return;
case ConformanceResponse::kSkipped:
@@ -400,6 +405,17 @@ void ConformanceTestSuite::RunValidJsonTestWithProtobufInput(
equivalent_text_format, conformance::JSON);
}
+void ConformanceTestSuite::RunValidProtobufTest(
+ const string& test_name, const TestAllTypes& input,
+ const string& equivalent_text_format) {
+ RunValidInputTest("ProtobufInput." + test_name + ".ProtobufOutput",
+ input.SerializeAsString(), conformance::PROTOBUF,
+ equivalent_text_format, conformance::PROTOBUF);
+ RunValidInputTest("ProtobufInput." + test_name + ".JsonOutput",
+ input.SerializeAsString(), conformance::PROTOBUF,
+ equivalent_text_format, conformance::JSON);
+}
+
// According to proto3 JSON specification, JSON serializers follow more strict
// rules than parsers (e.g., a serializer must serialize int32 values as JSON
// numbers while the parser is allowed to accept them as JSON strings). This
@@ -638,18 +654,22 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
RunValidJsonTest("HelloWorld", "{\"optionalString\":\"Hello, World!\"}",
"optional_string: 'Hello, World!'");
+ // NOTE: The spec for JSON support is still being sorted out, these may not
+ // all be correct.
// Test field name conventions.
RunValidJsonTest(
"FieldNameInSnakeCase",
R"({
"fieldname1": 1,
"fieldName2": 2,
- "FieldName3": 3
+ "fieldName3": 3,
+ "fieldName4": 4
})",
R"(
fieldname1: 1
field_name2: 2
_field_name3: 3
+ field__name4_: 4
)");
RunValidJsonTest(
"FieldNameWithNumbers",
@@ -679,6 +699,24 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
FIELD_NAME11: 11
FIELD_name12: 12
)");
+ RunValidJsonTest(
+ "FieldNameWithDoubleUnderscores",
+ R"({
+ "fieldName13": 13,
+ "fieldName14": 14,
+ "fieldName15": 15,
+ "fieldName16": 16,
+ "fieldName17": 17,
+ "fieldName18": 18
+ })",
+ R"(
+ __field_name13: 13
+ __Field_name14: 14
+ field__name15: 15
+ field__Name16: 16
+ field_name17__: 17
+ Field_name18__: 18
+ )");
// Using the original proto field name in JSON is also allowed.
RunValidJsonTest(
"OriginalProtoFieldName",
@@ -686,6 +724,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
"fieldname1": 1,
"field_name2": 2,
"_field_name3": 3,
+ "field__name4_": 4,
"field0name5": 5,
"field_0_name6": 6,
"fieldName7": 7,
@@ -693,12 +732,19 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
"field_Name9": 9,
"Field_Name10": 10,
"FIELD_NAME11": 11,
- "FIELD_name12": 12
+ "FIELD_name12": 12,
+ "__field_name13": 13,
+ "__Field_name14": 14,
+ "field__name15": 15,
+ "field__Name16": 16,
+ "field_name17__": 17,
+ "Field_name18__": 18
})",
R"(
fieldname1: 1
field_name2: 2
_field_name3: 3
+ field__name4_: 4
field0name5: 5
field_0_name6: 6
fieldName7: 7
@@ -707,12 +753,22 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
Field_Name10: 10
FIELD_NAME11: 11
FIELD_name12: 12
+ __field_name13: 13
+ __Field_name14: 14
+ field__name15: 15
+ field__Name16: 16
+ field_name17__: 17
+ Field_name18__: 18
)");
// Field names can be escaped.
RunValidJsonTest(
"FieldNameEscaped",
R"({"fieldn\u0061me1": 1})",
"fieldname1: 1");
+ // String ends with escape character.
+ ExpectParseFailureForJson(
+ "StringEndsWithEscapeChar",
+ "{\"optionalString\": \"abc\\");
// Field names must be quoted (or it's not valid JSON).
ExpectParseFailureForJson(
"FieldNameNotQuoted",
@@ -721,6 +777,17 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
ExpectParseFailureForJson(
"TrailingCommaInAnObject",
R"({"fieldname1":1,})");
+ ExpectParseFailureForJson(
+ "TrailingCommaInAnObjectWithSpace",
+ R"({"fieldname1":1 ,})");
+ ExpectParseFailureForJson(
+ "TrailingCommaInAnObjectWithSpaceCommaSpace",
+ R"({"fieldname1":1 , })");
+ ExpectParseFailureForJson(
+ "TrailingCommaInAnObjectWithNewlines",
+ R"({
+ "fieldname1":1,
+ })");
// JSON doesn't support comments.
ExpectParseFailureForJson(
"JsonWithComments",
@@ -728,6 +795,42 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
// This is a comment.
"fieldname1": 1
})");
+ // JSON spec says whitespace doesn't matter, so try a few spacings to be sure.
+ RunValidJsonTest(
+ "OneLineNoSpaces",
+ "{\"optionalInt32\":1,\"optionalInt64\":2}",
+ R"(
+ optional_int32: 1
+ optional_int64: 2
+ )");
+ RunValidJsonTest(
+ "OneLineWithSpaces",
+ "{ \"optionalInt32\" : 1 , \"optionalInt64\" : 2 }",
+ R"(
+ optional_int32: 1
+ optional_int64: 2
+ )");
+ RunValidJsonTest(
+ "MultilineNoSpaces",
+ "{\n\"optionalInt32\"\n:\n1\n,\n\"optionalInt64\"\n:\n2\n}",
+ R"(
+ optional_int32: 1
+ optional_int64: 2
+ )");
+ RunValidJsonTest(
+ "MultilineWithSpaces",
+ "{\n \"optionalInt32\" : 1\n ,\n \"optionalInt64\" : 2\n}\n",
+ R"(
+ optional_int32: 1
+ optional_int64: 2
+ )");
+ // Missing comma between key/value pairs.
+ ExpectParseFailureForJson(
+ "MissingCommaOneLine",
+ "{ \"optionalInt32\": 1 \"optionalInt64\": 2 }");
+ ExpectParseFailureForJson(
+ "MissingCommaMultiline",
+ "{\n \"optionalInt32\": 1\n \"optionalInt64\": 2\n}");
// Duplicated field names are not allowed.
ExpectParseFailureForJson(
"FieldNameDuplicate",
@@ -747,18 +850,22 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
"optionalNestedMessage": {a: 1},
"optional_nested_message": {}
})");
+ // NOTE: The spec for JSON support is still being sorted out, these may not
+ // all be correct.
// Serializers should use lowerCamelCase by default.
RunValidJsonTestWithValidator(
"FieldNameInLowerCamelCase",
R"({
"fieldname1": 1,
"fieldName2": 2,
- "FieldName3": 3
+ "fieldName3": 3,
+ "fieldName4": 4
})",
[](const Json::Value& value) {
return value.isMember("fieldname1") &&
value.isMember("fieldName2") &&
- value.isMember("FieldName3");
+ value.isMember("fieldName3") &&
+ value.isMember("fieldName4");
});
RunValidJsonTestWithValidator(
"FieldNameWithNumbers",
@@ -788,6 +895,24 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
value.isMember("fIELDNAME11") &&
value.isMember("fIELDName12");
});
+ RunValidJsonTestWithValidator(
+ "FieldNameWithDoubleUnderscores",
+ R"({
+ "fieldName13": 13,
+ "fieldName14": 14,
+ "fieldName15": 15,
+ "fieldName16": 16,
+ "fieldName17": 17,
+ "fieldName18": 18
+ })",
+ [](const Json::Value& value) {
+ return value.isMember("fieldName13") &&
+ value.isMember("fieldName14") &&
+ value.isMember("fieldName15") &&
+ value.isMember("fieldName16") &&
+ value.isMember("fieldName17") &&
+ value.isMember("fieldName18");
+ });
// Integer fields.
RunValidJsonTest(
@@ -814,18 +939,26 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
"Uint64FieldMaxValue",
R"({"optionalUint64": "18446744073709551615"})",
"optional_uint64: 18446744073709551615");
+ // While not the largest Int64, this is the largest
+ // Int64 which can be exactly represented within an
+ // IEEE-754 64-bit float, which is the expected level
+ // of interoperability guarantee. Larger values may
+ // work in some implementations, but should not be
+ // relied upon.
RunValidJsonTest(
"Int64FieldMaxValueNotQuoted",
- R"({"optionalInt64": 9223372036854775807})",
- "optional_int64: 9223372036854775807");
+ R"({"optionalInt64": 9223372036854774784})",
+ "optional_int64: 9223372036854774784");
RunValidJsonTest(
"Int64FieldMinValueNotQuoted",
R"({"optionalInt64": -9223372036854775808})",
"optional_int64: -9223372036854775808");
+ // Largest interoperable Uint64; see comment above
+ // for Int64FieldMaxValueNotQuoted.
RunValidJsonTest(
"Uint64FieldMaxValueNotQuoted",
- R"({"optionalUint64": 18446744073709551615})",
- "optional_uint64: 18446744073709551615");
+ R"({"optionalUint64": 18446744073709549568})",
+ "optional_uint64: 18446744073709549568");
// Values can be represented as JSON strings.
RunValidJsonTest(
"Int32FieldStringValue",
@@ -1217,6 +1350,64 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
ExpectParseFailureForJson(
"OneofFieldDuplicate",
R"({"oneofUint32": 1, "oneofString": "test"})");
+ // Ensure zero values for oneof make it out/backs.
+ {
+ TestAllTypes message;
+ message.set_oneof_uint32(0);
+ RunValidProtobufTest(
+ "OneofZeroUint32", message, "oneof_uint32: 0");
+ message.mutable_oneof_nested_message()->set_a(0);
+ RunValidProtobufTest(
+ "OneofZeroMessage", message, "oneof_nested_message: {}");
+ message.set_oneof_string("");
+ RunValidProtobufTest(
+ "OneofZeroString", message, "oneof_string: \"\"");
+ message.set_oneof_bytes("");
+ RunValidProtobufTest(
+ "OneofZeroBytes", message, "oneof_bytes: \"\"");
+ message.set_oneof_bool(false);
+ RunValidProtobufTest(
+ "OneofZeroBool", message, "oneof_bool: false");
+ message.set_oneof_uint64(0);
+ RunValidProtobufTest(
+ "OneofZeroUint64", message, "oneof_uint64: 0");
+ message.set_oneof_float(0.0f);
+ RunValidProtobufTest(
+ "OneofZeroFloat", message, "oneof_float: 0");
+ message.set_oneof_double(0.0);
+ RunValidProtobufTest(
+ "OneofZeroDouble", message, "oneof_double: 0");
+ message.set_oneof_enum(TestAllTypes::FOO);
+ RunValidProtobufTest(
+ "OneofZeroEnum", message, "oneof_enum: FOO");
+ }
+ RunValidJsonTest(
+ "OneofZeroUint32",
+ R"({"oneofUint32": 0})", "oneof_uint32: 0");
+ RunValidJsonTest(
+ "OneofZeroMessage",
+ R"({"oneofNestedMessage": {}})", "oneof_nested_message: {}");
+ RunValidJsonTest(
+ "OneofZeroString",
+ R"({"oneofString": ""})", "oneof_string: \"\"");
+ RunValidJsonTest(
+ "OneofZeroBytes",
+ R"({"oneofBytes": ""})", "oneof_bytes: \"\"");
+ RunValidJsonTest(
+ "OneofZeroBool",
+ R"({"oneofBool": false})", "oneof_bool: false");
+ RunValidJsonTest(
+ "OneofZeroUint64",
+ R"({"oneofUint64": 0})", "oneof_uint64: 0");
+ RunValidJsonTest(
+ "OneofZeroFloat",
+ R"({"oneofFloat": 0.0})", "oneof_float: 0");
+ RunValidJsonTest(
+ "OneofZeroDouble",
+ R"({"oneofDouble": 0.0})", "oneof_double: 0");
+ RunValidJsonTest(
+ "OneofZeroEnum",
+ R"({"oneofEnum":"FOO"})", "oneof_enum: FOO");
// Repeated fields.
RunValidJsonTest(
@@ -1273,6 +1464,15 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
ExpectParseFailureForJson(
"RepeatedFieldTrailingComma",
R"({"repeatedInt32": [1, 2, 3, 4,]})");
+ ExpectParseFailureForJson(
+ "RepeatedFieldTrailingCommaWithSpace",
+ "{\"repeatedInt32\": [1, 2, 3, 4 ,]}");
+ ExpectParseFailureForJson(
+ "RepeatedFieldTrailingCommaWithSpaceCommaSpace",
+ "{\"repeatedInt32\": [1, 2, 3, 4 , ]}");
+ ExpectParseFailureForJson(
+ "RepeatedFieldTrailingCommaWithNewlines",
+ "{\"repeatedInt32\": [\n 1,\n 2,\n 3,\n 4,\n]}");
// Map fields.
RunValidJsonTest(
@@ -1391,6 +1591,18 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
"MapFieldValueIsNull",
R"({"mapInt32Int32": {"0": null}})");
+ // http://www.rfc-editor.org/rfc/rfc7159.txt says strings have to use double
+ // quotes.
+ ExpectParseFailureForJson(
+ "StringFieldSingleQuoteKey",
+ R"({'optionalString': "Hello world!"})");
+ ExpectParseFailureForJson(
+ "StringFieldSingleQuoteValue",
+ R"({"optionalString": 'Hello world!'})");
+ ExpectParseFailureForJson(
+ "StringFieldSingleQuoteBoth",
+ R"({'optionalString': 'Hello world!'})");
+
// Wrapper types.
RunValidJsonTest(
"OptionalBoolWrapper",
diff --git a/conformance/conformance_test.h b/conformance/conformance_test.h
index c9c5213c..56689318 100644
--- a/conformance/conformance_test.h
+++ b/conformance/conformance_test.h
@@ -133,6 +133,9 @@ class ConformanceTestSuite {
void RunValidJsonTestWithProtobufInput(const string& test_name,
const conformance::TestAllTypes& input,
const string& equivalent_text_format);
+ void RunValidProtobufTest(const string& test_name,
+ const conformance::TestAllTypes& input,
+ const string& equivalent_text_format);
typedef std::function<bool(const Json::Value&)> Validator;
void RunValidJsonTestWithValidator(const string& test_name,
diff --git a/conformance/failure_list_cpp.txt b/conformance/failure_list_cpp.txt
index 839e5210..5e17176e 100644
--- a/conformance/failure_list_cpp.txt
+++ b/conformance/failure_list_cpp.txt
@@ -22,16 +22,22 @@ JsonInput.FieldMaskInvalidCharacter
JsonInput.FieldNameDuplicate
JsonInput.FieldNameDuplicateDifferentCasing1
JsonInput.FieldNameDuplicateDifferentCasing2
-JsonInput.FieldNameInLowerCamelCase.Validator
-JsonInput.FieldNameInSnakeCase.JsonOutput
-JsonInput.FieldNameInSnakeCase.ProtobufOutput
JsonInput.FieldNameNotQuoted
JsonInput.MapFieldValueIsNull
JsonInput.RepeatedFieldMessageElementIsNull
JsonInput.RepeatedFieldPrimitiveElementIsNull
JsonInput.RepeatedFieldTrailingComma
+JsonInput.RepeatedFieldTrailingCommaWithNewlines
+JsonInput.RepeatedFieldTrailingCommaWithSpace
+JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace
+JsonInput.StringFieldSingleQuoteBoth
+JsonInput.StringFieldSingleQuoteKey
+JsonInput.StringFieldSingleQuoteValue
JsonInput.StringFieldUppercaseEscapeLetter
JsonInput.TrailingCommaInAnObject
+JsonInput.TrailingCommaInAnObjectWithNewlines
+JsonInput.TrailingCommaInAnObjectWithSpace
+JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace
JsonInput.WrapperTypesWithNullValue.JsonOutput
JsonInput.WrapperTypesWithNullValue.ProtobufOutput
ProtobufInput.PrematureEofBeforeKnownRepeatedValue.MESSAGE
diff --git a/conformance/failure_list_csharp.txt b/conformance/failure_list_csharp.txt
index e7de4b96..d8bfe1bb 100644
--- a/conformance/failure_list_csharp.txt
+++ b/conformance/failure_list_csharp.txt
@@ -1,11 +1,4 @@
-JsonInput.FieldNameInLowerCamelCase.Validator
-JsonInput.FieldNameInSnakeCase.JsonOutput
-JsonInput.FieldNameInSnakeCase.ProtobufOutput
JsonInput.FieldNameWithMixedCases.JsonOutput
JsonInput.FieldNameWithMixedCases.ProtobufOutput
JsonInput.FieldNameWithMixedCases.Validator
-JsonInput.Int64FieldMaxValueNotQuoted.JsonOutput
-JsonInput.Int64FieldMaxValueNotQuoted.ProtobufOutput
JsonInput.OriginalProtoFieldName.JsonOutput
-JsonInput.Uint64FieldMaxValueNotQuoted.JsonOutput
-JsonInput.Uint64FieldMaxValueNotQuoted.ProtobufOutput
diff --git a/conformance/failure_list_java.txt b/conformance/failure_list_java.txt
index 850712bd..b2122c8b 100644
--- a/conformance/failure_list_java.txt
+++ b/conformance/failure_list_java.txt
@@ -20,8 +20,13 @@ JsonInput.DoubleFieldNegativeInfinityNotQuoted
JsonInput.EnumFieldNotQuoted
JsonInput.FieldMaskInvalidCharacter
JsonInput.FieldNameDuplicate
+JsonInput.FieldNameInLowerCamelCase.Validator
JsonInput.FieldNameInSnakeCase.JsonOutput
+JsonInput.FieldNameInSnakeCase.ProtobufOutput
JsonInput.FieldNameNotQuoted
+JsonInput.FieldNameWithDoubleUnderscores.JsonOutput
+JsonInput.FieldNameWithDoubleUnderscores.ProtobufOutput
+JsonInput.FieldNameWithDoubleUnderscores.Validator
JsonInput.FloatFieldInfinityNotQuoted
JsonInput.FloatFieldNanNotQuoted
JsonInput.FloatFieldNegativeInfinityNotQuoted
@@ -35,6 +40,9 @@ JsonInput.OriginalProtoFieldName.JsonOutput
JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
JsonInput.StringFieldNotAString
+JsonInput.StringFieldSingleQuoteBoth
+JsonInput.StringFieldSingleQuoteKey
+JsonInput.StringFieldSingleQuoteValue
JsonInput.StringFieldSurrogateInWrongOrder
JsonInput.StringFieldUnpairedHighSurrogate
JsonInput.StringFieldUnpairedLowSurrogate
diff --git a/conformance/failure_list_objc.txt b/conformance/failure_list_objc.txt
index 5dac3501..dd538c10 100644
--- a/conformance/failure_list_objc.txt
+++ b/conformance/failure_list_objc.txt
@@ -1,4 +1,4 @@
-# No tests currently failing.
+# All tests currently passing.
#
-# json input or output tests are skipped (in conformance_objc.m) as mobile
-# platforms don't support json wire format to avoid code bloat.
+# JSON input or output tests are skipped (in conformance_objc.m) as mobile
+# platforms don't support JSON wire format to avoid code bloat.
diff --git a/conformance/failure_list_python.txt b/conformance/failure_list_python.txt
index 550a043f..d38b7828 100644
--- a/conformance/failure_list_python.txt
+++ b/conformance/failure_list_python.txt
@@ -19,9 +19,6 @@ JsonInput.EnumFieldNumericValueZero.ProtobufOutput
JsonInput.EnumFieldUnknownValue.Validator
JsonInput.FieldMask.ProtobufOutput
JsonInput.FieldMaskInvalidCharacter
-JsonInput.FieldNameInLowerCamelCase.Validator
-JsonInput.FieldNameInSnakeCase.JsonOutput
-JsonInput.FieldNameInSnakeCase.ProtobufOutput
JsonInput.FloatFieldInfinityNotQuoted
JsonInput.FloatFieldNanNotQuoted
JsonInput.FloatFieldNegativeInfinityNotQuoted
@@ -35,6 +32,8 @@ JsonInput.Int32FieldMaxFloatValue.JsonOutput
JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
JsonInput.Int32FieldMinFloatValue.JsonOutput
JsonInput.Int32FieldMinFloatValue.ProtobufOutput
+JsonInput.OneofZeroMessage.JsonOutput
+JsonInput.OneofZeroMessage.ProtobufOutput
JsonInput.OriginalProtoFieldName.JsonOutput
JsonInput.OriginalProtoFieldName.ProtobufOutput
JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
diff --git a/conformance/failure_list_python_cpp.txt b/conformance/failure_list_python_cpp.txt
index 1eb916ab..84d9fccd 100644
--- a/conformance/failure_list_python_cpp.txt
+++ b/conformance/failure_list_python_cpp.txt
@@ -28,9 +28,6 @@ JsonInput.EnumFieldNumericValueZero.ProtobufOutput
JsonInput.EnumFieldUnknownValue.Validator
JsonInput.FieldMask.ProtobufOutput
JsonInput.FieldMaskInvalidCharacter
-JsonInput.FieldNameInLowerCamelCase.Validator
-JsonInput.FieldNameInSnakeCase.JsonOutput
-JsonInput.FieldNameInSnakeCase.ProtobufOutput
JsonInput.FloatFieldInfinityNotQuoted
JsonInput.FloatFieldNanNotQuoted
JsonInput.FloatFieldNegativeInfinityNotQuoted
@@ -44,6 +41,8 @@ JsonInput.Int32FieldMaxFloatValue.JsonOutput
JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
JsonInput.Int32FieldMinFloatValue.JsonOutput
JsonInput.Int32FieldMinFloatValue.ProtobufOutput
+JsonInput.OneofZeroMessage.JsonOutput
+JsonInput.OneofZeroMessage.ProtobufOutput
JsonInput.OriginalProtoFieldName.JsonOutput
JsonInput.OriginalProtoFieldName.ProtobufOutput
JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
diff --git a/conformance/failure_list_ruby.txt b/conformance/failure_list_ruby.txt
index 7c12da06..2a533aa5 100644
--- a/conformance/failure_list_ruby.txt
+++ b/conformance/failure_list_ruby.txt
@@ -58,7 +58,12 @@ JsonInput.EnumFieldNumericValueZero.ProtobufOutput
JsonInput.EnumFieldUnknownValue.Validator
JsonInput.FieldMask.JsonOutput
JsonInput.FieldMask.ProtobufOutput
+JsonInput.FieldNameInLowerCamelCase.Validator
JsonInput.FieldNameInSnakeCase.JsonOutput
+JsonInput.FieldNameInSnakeCase.ProtobufOutput
+JsonInput.FieldNameWithDoubleUnderscores.JsonOutput
+JsonInput.FieldNameWithDoubleUnderscores.ProtobufOutput
+JsonInput.FieldNameWithDoubleUnderscores.Validator
JsonInput.FieldNameWithMixedCases.JsonOutput
JsonInput.FieldNameWithMixedCases.ProtobufOutput
JsonInput.FieldNameWithMixedCases.Validator
@@ -103,6 +108,14 @@ JsonInput.MessageMapField.JsonOutput
JsonInput.MessageMapField.ProtobufOutput
JsonInput.MessageRepeatedField.JsonOutput
JsonInput.MessageRepeatedField.ProtobufOutput
+JsonInput.OneofZeroDouble.JsonOutput
+JsonInput.OneofZeroDouble.ProtobufOutput
+JsonInput.OneofZeroFloat.JsonOutput
+JsonInput.OneofZeroFloat.ProtobufOutput
+JsonInput.OneofZeroUint32.JsonOutput
+JsonInput.OneofZeroUint32.ProtobufOutput
+JsonInput.OneofZeroUint64.JsonOutput
+JsonInput.OneofZeroUint64.ProtobufOutput
JsonInput.OptionalBoolWrapper.JsonOutput
JsonInput.OptionalBoolWrapper.ProtobufOutput
JsonInput.OptionalBytesWrapper.JsonOutput
@@ -145,6 +158,7 @@ JsonInput.RepeatedUint32Wrapper.JsonOutput
JsonInput.RepeatedUint32Wrapper.ProtobufOutput
JsonInput.RepeatedUint64Wrapper.JsonOutput
JsonInput.RepeatedUint64Wrapper.ProtobufOutput
+JsonInput.StringEndsWithEscapeChar
JsonInput.StringFieldNotAString
JsonInput.StringFieldSurrogateInWrongOrder
JsonInput.StringFieldSurrogatePair.JsonOutput
diff --git a/csharp/.gitignore b/csharp/.gitignore
index c88f741e..8ba88499 100644
--- a/csharp/.gitignore
+++ b/csharp/.gitignore
@@ -1,16 +1,10 @@
-#
-# Untracked directories
-#
-src/AddressBook/bin
-src/AddressBook/obj
-src/Google.Protobuf/bin/
-src/Google.Protobuf/obj/
-src/Google.Protobuf.Conformance/bin/
-src/Google.Protobuf.Conformance/obj/
-src/Google.Protobuf.Test/bin/
-src/Google.Protobuf.Test/obj/
-src/Google.Protobuf.JsonDump/bin/
-src/Google.Protobuf.JsonDump/obj/
+# Output
+bin
+obj
+project.lock.json
+TestResult.xml
+
+# Possibly legacy now?
mono/bin
mono/tmp
mono/protoc
@@ -23,6 +17,7 @@ lib/NUnit
#
# Untracked files
#
+.vs
*.user
*.suo
*.nupkg
diff --git a/csharp/Google.Protobuf.Tools.nuspec b/csharp/Google.Protobuf.Tools.nuspec
index e4240dae..24b4a776 100644
--- a/csharp/Google.Protobuf.Tools.nuspec
+++ b/csharp/Google.Protobuf.Tools.nuspec
@@ -5,7 +5,7 @@
<title>Google Protocol Buffers tools</title>
<summary>Tools for Protocol Buffers - Google's data interchange format.</summary>
<description>See project site for more info.</description>
- <version>3.0.0-beta3</version>
+ <version>3.0.0</version>
<authors>Google Inc.</authors>
<owners>protobuf-packages</owners>
<licenseUrl>https://github.com/google/protobuf/blob/master/LICENSE</licenseUrl>
diff --git a/csharp/README.md b/csharp/README.md
index 8c3993e0..ddf1d2be 100644
--- a/csharp/README.md
+++ b/csharp/README.md
@@ -9,8 +9,8 @@ Usage
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`
+You will also want to install the `Google.Protobuf.Tools` NuGet package, which
+contains precompiled version of `protoc.exe` and a copy of well known `.proto`
files under the package's `tools` directory.
To generate C# files from your `.proto` files, invoke `protoc` with the
diff --git a/csharp/build_packages.bat b/csharp/build_packages.bat
index 1502f063..37732e7c 100644
--- a/csharp/build_packages.bat
+++ b/csharp/build_packages.bat
@@ -1,10 +1,7 @@
@rem Builds Google.Protobuf NuGet packages
-@rem Adjust the location of nuget.exe
-set NUGET=C:\nuget\nuget.exe
-
-@rem Build src/Google.Protobuf.sln solution in Release configuration first.
-%NUGET% pack src\Google.Protobuf\Google.Protobuf.nuspec -Symbols || goto :error
+dotnet restore src
+dotnet pack -c Release src\Google.Protobuf || goto :error
goto :EOF
diff --git a/csharp/buildall.sh b/csharp/buildall.sh
index 45af705f..cab32229 100755
--- a/csharp/buildall.sh
+++ b/csharp/buildall.sh
@@ -1,17 +1,16 @@
#!/bin/bash
-# Use mono to build solution and run all tests.
-# Adjust these to reflect the location of nunit-console in your system.
-NUNIT_CONSOLE=nunit-console
-
-# The rest you can leave intact
CONFIG=Release
SRC=$(dirname $0)/src
set -ex
-echo Building the solution.
-xbuild /p:Configuration=$CONFIG $SRC/Google.Protobuf.sln
+echo Building relevant projects.
+dotnet build -c $CONFIG $SRC/Google.Protobuf $SRC/Google.Protobuf.Test $SRC/Google.Protobuf.Conformance
echo Running tests.
-$NUNIT_CONSOLE $SRC/Google.Protobuf.Test/bin/$CONFIG/Google.Protobuf.Test.dll
+# Only test netcoreapp1.0, which uses the .NET Core runtime.
+# If we want to test the .NET 4.5 version separately, we could
+# run Mono explicitly. However, we don't have any differences between
+# the .NET 4.5 and netstandard1.0 assemblies.
+dotnet test -c $CONFIG -f netcoreapp1.0 $SRC/Google.Protobuf.Test
diff --git a/csharp/src/AddressBook/AddressBook.csproj b/csharp/src/AddressBook/AddressBook.csproj
deleted file mode 100644
index 8f8ca7e2..00000000
--- a/csharp/src/AddressBook/AddressBook.csproj
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.30729</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{A31F5FB2-4FF3-432A-B35B-5CD203606311}</ProjectGuid>
- <OutputType>Exe</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Google.Protobuf.Examples.AddressBook</RootNamespace>
- <AssemblyName>AddressBook</AssemblyName>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <StartupObject>Google.Protobuf.Examples.AddressBook.Program</StartupObject>
- <TargetFrameworkProfile>
- </TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug</OutputPath>
- <IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <NoStdLib>true</NoStdLib>
- <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
- <Prefer32Bit>false</Prefer32Bit>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release</OutputPath>
- <IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <NoStdLib>true</NoStdLib>
- <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
- <Prefer32Bit>false</Prefer32Bit>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="mscorlib" />
- <Reference Include="System" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="AddPerson.cs" />
- <Compile Include="Addressbook.cs" />
- <Compile Include="SampleUsage.cs" />
- <Compile Include="ListPeople.cs" />
- <Compile Include="Program.cs" />
- <Compile Include="Properties\AssemblyInfo.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj">
- <Project>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
- <Name>Google.Protobuf</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <None Include="app.config" />
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project> \ No newline at end of file
diff --git a/csharp/src/AddressBook/AddressBook.xproj b/csharp/src/AddressBook/AddressBook.xproj
new file mode 100644
index 00000000..4c9925e8
--- /dev/null
+++ b/csharp/src/AddressBook/AddressBook.xproj
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
+ <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
+ </PropertyGroup>
+ <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>afb63919-1e05-43b4-802a-8fb8c9b2f463</ProjectGuid>
+ <RootNamespace>AddressBook</RootNamespace>
+ <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
+ <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <SchemaVersion>2.0</SchemaVersion>
+ </PropertyGroup>
+ <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
+</Project> \ No newline at end of file
diff --git a/csharp/src/AddressBook/Properties/AssemblyInfo.cs b/csharp/src/AddressBook/Properties/AssemblyInfo.cs
deleted file mode 100644
index 9cb014c0..00000000
--- a/csharp/src/AddressBook/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-
-[assembly: AssemblyTitle("AddressBook")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("AddressBook")]
-[assembly: AssemblyCopyright("Copyright © 2015")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-[assembly: AssemblyVersion("3.0.0.0")]
-[assembly: AssemblyFileVersion("3.0.0.0")]
diff --git a/csharp/src/AddressBook/SampleUsage.cs b/csharp/src/AddressBook/SampleUsage.cs
index aaaedda4..941d865a 100644
--- a/csharp/src/AddressBook/SampleUsage.cs
+++ b/csharp/src/AddressBook/SampleUsage.cs
@@ -66,7 +66,7 @@ namespace Google.Protobuf.Examples.AddressBook
// The message performs a deep-comparison on equality:
if (restored.People.Count != 1 || !person.Equals(restored.People[0]))
{
- throw new ApplicationException("There is a bad person in here!");
+ throw new Exception("There is a bad person in here!");
}
}
}
diff --git a/csharp/src/AddressBook/app.config b/csharp/src/AddressBook/app.config
deleted file mode 100644
index a80813af..00000000
--- a/csharp/src/AddressBook/app.config
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0"?>
-<configuration>
- <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
diff --git a/csharp/src/AddressBook/project.json b/csharp/src/AddressBook/project.json
new file mode 100644
index 00000000..c500bdc2
--- /dev/null
+++ b/csharp/src/AddressBook/project.json
@@ -0,0 +1,20 @@
+{
+ "buildOptions": {
+ "debugType": "portable",
+ "emitEntryPoint": true,
+ "additionalArguments": [ "/main:Google.Protobuf.Examples.AddressBook.Program" ]
+ },
+ "dependencies": {
+ "Google.Protobuf": { "target": "project" }
+ },
+ "frameworks": {
+ "netcoreapp1.0": {
+ "dependencies": {
+ "Microsoft.NETCore.App": {
+ "type": "platform",
+ "version": "1.0.0"
+ }
+ }
+ }
+ }
+}
diff --git a/csharp/src/Google.Protobuf.Conformance/App.config b/csharp/src/Google.Protobuf.Conformance/App.config
deleted file mode 100644
index 8e156463..00000000
--- a/csharp/src/Google.Protobuf.Conformance/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<configuration>
- <startup>
- <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
- </startup>
-</configuration> \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Conformance/Conformance.cs b/csharp/src/Google.Protobuf.Conformance/Conformance.cs
index 5fcbff7c..431ac4fb 100644
--- a/csharp/src/Google.Protobuf.Conformance/Conformance.cs
+++ b/csharp/src/Google.Protobuf.Conformance/Conformance.cs
@@ -34,7 +34,7 @@ namespace Conformance {
"IAEoCUgAEhkKD3NlcmlhbGl6ZV9lcnJvchgGIAEoCUgAEhcKDXJ1bnRpbWVf",
"ZXJyb3IYAiABKAlIABIaChBwcm90b2J1Zl9wYXlsb2FkGAMgASgMSAASFgoM",
"anNvbl9wYXlsb2FkGAQgASgJSAASEQoHc2tpcHBlZBgFIAEoCUgAQggKBnJl",
- "c3VsdCLVMgoMVGVzdEFsbFR5cGVzEhYKDm9wdGlvbmFsX2ludDMyGAEgASgF",
+ "c3VsdCKCNQoMVGVzdEFsbFR5cGVzEhYKDm9wdGlvbmFsX2ludDMyGAEgASgF",
"EhYKDm9wdGlvbmFsX2ludDY0GAIgASgDEhcKD29wdGlvbmFsX3VpbnQzMhgD",
"IAEoDRIXCg9vcHRpb25hbF91aW50NjQYBCABKAQSFwoPb3B0aW9uYWxfc2lu",
"dDMyGAUgASgREhcKD29wdGlvbmFsX3NpbnQ2NBgGIAEoEhIYChBvcHRpb25h",
@@ -102,93 +102,100 @@ namespace Conformance {
"TWFwU3RyaW5nRm9yZWlnbkVudW1FbnRyeRIWCgxvbmVvZl91aW50MzIYbyAB",
"KA1IABJHChRvbmVvZl9uZXN0ZWRfbWVzc2FnZRhwIAEoCzInLmNvbmZvcm1h",
"bmNlLlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlSAASFgoMb25lb2Zfc3Ry",
- "aW5nGHEgASgJSAASFQoLb25lb2ZfYnl0ZXMYciABKAxIABI6ChVvcHRpb25h",
- "bF9ib29sX3dyYXBwZXIYyQEgASgLMhouZ29vZ2xlLnByb3RvYnVmLkJvb2xW",
- "YWx1ZRI8ChZvcHRpb25hbF9pbnQzMl93cmFwcGVyGMoBIAEoCzIbLmdvb2ds",
- "ZS5wcm90b2J1Zi5JbnQzMlZhbHVlEjwKFm9wdGlvbmFsX2ludDY0X3dyYXBw",
- "ZXIYywEgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUSPgoXb3B0",
- "aW9uYWxfdWludDMyX3dyYXBwZXIYzAEgASgLMhwuZ29vZ2xlLnByb3RvYnVm",
- "LlVJbnQzMlZhbHVlEj4KF29wdGlvbmFsX3VpbnQ2NF93cmFwcGVyGM0BIAEo",
- "CzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50NjRWYWx1ZRI8ChZvcHRpb25hbF9m",
- "bG9hdF93cmFwcGVyGM4BIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5GbG9hdFZh",
- "bHVlEj4KF29wdGlvbmFsX2RvdWJsZV93cmFwcGVyGM8BIAEoCzIcLmdvb2ds",
- "ZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI+ChdvcHRpb25hbF9zdHJpbmdfd3Jh",
- "cHBlchjQASABKAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUSPAoW",
- "b3B0aW9uYWxfYnl0ZXNfd3JhcHBlchjRASABKAsyGy5nb29nbGUucHJvdG9i",
- "dWYuQnl0ZXNWYWx1ZRI6ChVyZXBlYXRlZF9ib29sX3dyYXBwZXIY0wEgAygL",
- "MhouZ29vZ2xlLnByb3RvYnVmLkJvb2xWYWx1ZRI8ChZyZXBlYXRlZF9pbnQz",
- "Ml93cmFwcGVyGNQBIAMoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVl",
- "EjwKFnJlcGVhdGVkX2ludDY0X3dyYXBwZXIY1QEgAygLMhsuZ29vZ2xlLnBy",
- "b3RvYnVmLkludDY0VmFsdWUSPgoXcmVwZWF0ZWRfdWludDMyX3dyYXBwZXIY",
- "1gEgAygLMhwuZ29vZ2xlLnByb3RvYnVmLlVJbnQzMlZhbHVlEj4KF3JlcGVh",
- "dGVkX3VpbnQ2NF93cmFwcGVyGNcBIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5V",
- "SW50NjRWYWx1ZRI8ChZyZXBlYXRlZF9mbG9hdF93cmFwcGVyGNgBIAMoCzIb",
- "Lmdvb2dsZS5wcm90b2J1Zi5GbG9hdFZhbHVlEj4KF3JlcGVhdGVkX2RvdWJs",
- "ZV93cmFwcGVyGNkBIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1",
- "ZRI+ChdyZXBlYXRlZF9zdHJpbmdfd3JhcHBlchjaASADKAsyHC5nb29nbGUu",
- "cHJvdG9idWYuU3RyaW5nVmFsdWUSPAoWcmVwZWF0ZWRfYnl0ZXNfd3JhcHBl",
- "chjbASADKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZRI1ChFvcHRp",
- "b25hbF9kdXJhdGlvbhitAiABKAsyGS5nb29nbGUucHJvdG9idWYuRHVyYXRp",
- "b24SNwoSb3B0aW9uYWxfdGltZXN0YW1wGK4CIAEoCzIaLmdvb2dsZS5wcm90",
- "b2J1Zi5UaW1lc3RhbXASOAoTb3B0aW9uYWxfZmllbGRfbWFzaxivAiABKAsy",
- "Gi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNrEjEKD29wdGlvbmFsX3N0cnVj",
- "dBiwAiABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0EisKDG9wdGlvbmFs",
- "X2FueRixAiABKAsyFC5nb29nbGUucHJvdG9idWYuQW55Ei8KDm9wdGlvbmFs",
- "X3ZhbHVlGLICIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5WYWx1ZRI1ChFyZXBl",
- "YXRlZF9kdXJhdGlvbhi3AiADKAsyGS5nb29nbGUucHJvdG9idWYuRHVyYXRp",
- "b24SNwoScmVwZWF0ZWRfdGltZXN0YW1wGLgCIAMoCzIaLmdvb2dsZS5wcm90",
- "b2J1Zi5UaW1lc3RhbXASNwoScmVwZWF0ZWRfZmllbGRtYXNrGLkCIAMoCzIa",
- "Lmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2sSMQoPcmVwZWF0ZWRfc3RydWN0",
- "GMQCIAMoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSKwoMcmVwZWF0ZWRf",
- "YW55GLsCIAMoCzIULmdvb2dsZS5wcm90b2J1Zi5BbnkSLwoOcmVwZWF0ZWRf",
- "dmFsdWUYvAIgAygLMhYuZ29vZ2xlLnByb3RvYnVmLlZhbHVlEhMKCmZpZWxk",
- "bmFtZTEYkQMgASgFEhQKC2ZpZWxkX25hbWUyGJIDIAEoBRIVCgxfZmllbGRf",
- "bmFtZTMYkwMgASgFEhYKDWZpZWxkX19uYW1lNF8YlAMgASgFEhQKC2ZpZWxk",
- "MG5hbWU1GJUDIAEoBRIWCg1maWVsZF8wX25hbWU2GJYDIAEoBRITCgpmaWVs",
- "ZE5hbWU3GJcDIAEoBRITCgpGaWVsZE5hbWU4GJgDIAEoBRIUCgtmaWVsZF9O",
- "YW1lORiZAyABKAUSFQoMRmllbGRfTmFtZTEwGJoDIAEoBRIVCgxGSUVMRF9O",
- "QU1FMTEYmwMgASgFEhUKDEZJRUxEX25hbWUxMhicAyABKAUaSgoNTmVzdGVk",
- "TWVzc2FnZRIJCgFhGAEgASgFEi4KC2NvcmVjdXJzaXZlGAIgASgLMhkuY29u",
- "Zm9ybWFuY2UuVGVzdEFsbFR5cGVzGjQKEk1hcEludDMySW50MzJFbnRyeRIL",
- "CgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAU6AjgBGjQKEk1hcEludDY0SW50",
- "NjRFbnRyeRILCgNrZXkYASABKAMSDQoFdmFsdWUYAiABKAM6AjgBGjYKFE1h",
- "cFVpbnQzMlVpbnQzMkVudHJ5EgsKA2tleRgBIAEoDRINCgV2YWx1ZRgCIAEo",
- "DToCOAEaNgoUTWFwVWludDY0VWludDY0RW50cnkSCwoDa2V5GAEgASgEEg0K",
- "BXZhbHVlGAIgASgEOgI4ARo2ChRNYXBTaW50MzJTaW50MzJFbnRyeRILCgNr",
- "ZXkYASABKBESDQoFdmFsdWUYAiABKBE6AjgBGjYKFE1hcFNpbnQ2NFNpbnQ2",
- "NEVudHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1ZRgCIAEoEjoCOAEaOAoWTWFw",
- "Rml4ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkYASABKAcSDQoFdmFsdWUYAiAB",
- "KAc6AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSCwoDa2V5GAEgASgG",
- "Eg0KBXZhbHVlGAIgASgGOgI4ARo6ChhNYXBTZml4ZWQzMlNmaXhlZDMyRW50",
- "cnkSCwoDa2V5GAEgASgPEg0KBXZhbHVlGAIgASgPOgI4ARo6ChhNYXBTZml4",
- "ZWQ2NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEgASgQEg0KBXZhbHVlGAIgASgQ",
- "OgI4ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkSCwoDa2V5GAEgASgFEg0KBXZh",
- "bHVlGAIgASgCOgI4ARo1ChNNYXBJbnQzMkRvdWJsZUVudHJ5EgsKA2tleRgB",
- "IAEoBRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQTWFwQm9vbEJvb2xFbnRyeRIL",
- "CgNrZXkYASABKAgSDQoFdmFsdWUYAiABKAg6AjgBGjYKFE1hcFN0cmluZ1N0",
- "cmluZ0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEaNQoT",
- "TWFwU3RyaW5nQnl0ZXNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiAB",
- "KAw6AjgBGmYKG01hcFN0cmluZ05lc3RlZE1lc3NhZ2VFbnRyeRILCgNrZXkY",
- "ASABKAkSNgoFdmFsdWUYAiABKAsyJy5jb25mb3JtYW5jZS5UZXN0QWxsVHlw",
- "ZXMuTmVzdGVkTWVzc2FnZToCOAEaWwocTWFwU3RyaW5nRm9yZWlnbk1lc3Nh",
- "Z2VFbnRyeRILCgNrZXkYASABKAkSKgoFdmFsdWUYAiABKAsyGy5jb25mb3Jt",
- "YW5jZS5Gb3JlaWduTWVzc2FnZToCOAEaYAoYTWFwU3RyaW5nTmVzdGVkRW51",
- "bUVudHJ5EgsKA2tleRgBIAEoCRIzCgV2YWx1ZRgCIAEoDjIkLmNvbmZvcm1h",
- "bmNlLlRlc3RBbGxUeXBlcy5OZXN0ZWRFbnVtOgI4ARpVChlNYXBTdHJpbmdG",
- "b3JlaWduRW51bUVudHJ5EgsKA2tleRgBIAEoCRInCgV2YWx1ZRgCIAEoDjIY",
- "LmNvbmZvcm1hbmNlLkZvcmVpZ25FbnVtOgI4ASI5CgpOZXN0ZWRFbnVtEgcK",
- "A0ZPTxAAEgcKA0JBUhABEgcKA0JBWhACEhAKA05FRxD///////////8BQg0K",
- "C29uZW9mX2ZpZWxkIhsKDkZvcmVpZ25NZXNzYWdlEgkKAWMYASABKAUqNQoK",
- "V2lyZUZvcm1hdBIPCgtVTlNQRUNJRklFRBAAEgwKCFBST1RPQlVGEAESCAoE",
- "SlNPThACKkAKC0ZvcmVpZ25FbnVtEg8KC0ZPUkVJR05fRk9PEAASDwoLRk9S",
- "RUlHTl9CQVIQARIPCgtGT1JFSUdOX0JBWhACQiEKH2NvbS5nb29nbGUucHJv",
- "dG9idWYuY29uZm9ybWFuY2ViBnByb3RvMw=="));
+ "aW5nGHEgASgJSAASFQoLb25lb2ZfYnl0ZXMYciABKAxIABIUCgpvbmVvZl9i",
+ "b29sGHMgASgISAASFgoMb25lb2ZfdWludDY0GHQgASgESAASFQoLb25lb2Zf",
+ "ZmxvYXQYdSABKAJIABIWCgxvbmVvZl9kb3VibGUYdiABKAFIABI6CgpvbmVv",
+ "Zl9lbnVtGHcgASgOMiQuY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzLk5lc3Rl",
+ "ZEVudW1IABI6ChVvcHRpb25hbF9ib29sX3dyYXBwZXIYyQEgASgLMhouZ29v",
+ "Z2xlLnByb3RvYnVmLkJvb2xWYWx1ZRI8ChZvcHRpb25hbF9pbnQzMl93cmFw",
+ "cGVyGMoBIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVlEjwKFm9w",
+ "dGlvbmFsX2ludDY0X3dyYXBwZXIYywEgASgLMhsuZ29vZ2xlLnByb3RvYnVm",
+ "LkludDY0VmFsdWUSPgoXb3B0aW9uYWxfdWludDMyX3dyYXBwZXIYzAEgASgL",
+ "MhwuZ29vZ2xlLnByb3RvYnVmLlVJbnQzMlZhbHVlEj4KF29wdGlvbmFsX3Vp",
+ "bnQ2NF93cmFwcGVyGM0BIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50NjRW",
+ "YWx1ZRI8ChZvcHRpb25hbF9mbG9hdF93cmFwcGVyGM4BIAEoCzIbLmdvb2ds",
+ "ZS5wcm90b2J1Zi5GbG9hdFZhbHVlEj4KF29wdGlvbmFsX2RvdWJsZV93cmFw",
+ "cGVyGM8BIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI+Chdv",
+ "cHRpb25hbF9zdHJpbmdfd3JhcHBlchjQASABKAsyHC5nb29nbGUucHJvdG9i",
+ "dWYuU3RyaW5nVmFsdWUSPAoWb3B0aW9uYWxfYnl0ZXNfd3JhcHBlchjRASAB",
+ "KAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZRI6ChVyZXBlYXRlZF9i",
+ "b29sX3dyYXBwZXIY0wEgAygLMhouZ29vZ2xlLnByb3RvYnVmLkJvb2xWYWx1",
+ "ZRI8ChZyZXBlYXRlZF9pbnQzMl93cmFwcGVyGNQBIAMoCzIbLmdvb2dsZS5w",
+ "cm90b2J1Zi5JbnQzMlZhbHVlEjwKFnJlcGVhdGVkX2ludDY0X3dyYXBwZXIY",
+ "1QEgAygLMhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUSPgoXcmVwZWF0",
+ "ZWRfdWludDMyX3dyYXBwZXIY1gEgAygLMhwuZ29vZ2xlLnByb3RvYnVmLlVJ",
+ "bnQzMlZhbHVlEj4KF3JlcGVhdGVkX3VpbnQ2NF93cmFwcGVyGNcBIAMoCzIc",
+ "Lmdvb2dsZS5wcm90b2J1Zi5VSW50NjRWYWx1ZRI8ChZyZXBlYXRlZF9mbG9h",
+ "dF93cmFwcGVyGNgBIAMoCzIbLmdvb2dsZS5wcm90b2J1Zi5GbG9hdFZhbHVl",
+ "Ej4KF3JlcGVhdGVkX2RvdWJsZV93cmFwcGVyGNkBIAMoCzIcLmdvb2dsZS5w",
+ "cm90b2J1Zi5Eb3VibGVWYWx1ZRI+ChdyZXBlYXRlZF9zdHJpbmdfd3JhcHBl",
+ "chjaASADKAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUSPAoWcmVw",
+ "ZWF0ZWRfYnl0ZXNfd3JhcHBlchjbASADKAsyGy5nb29nbGUucHJvdG9idWYu",
+ "Qnl0ZXNWYWx1ZRI1ChFvcHRpb25hbF9kdXJhdGlvbhitAiABKAsyGS5nb29n",
+ "bGUucHJvdG9idWYuRHVyYXRpb24SNwoSb3B0aW9uYWxfdGltZXN0YW1wGK4C",
+ "IAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASOAoTb3B0aW9uYWxf",
+ "ZmllbGRfbWFzaxivAiABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNr",
+ "EjEKD29wdGlvbmFsX3N0cnVjdBiwAiABKAsyFy5nb29nbGUucHJvdG9idWYu",
+ "U3RydWN0EisKDG9wdGlvbmFsX2FueRixAiABKAsyFC5nb29nbGUucHJvdG9i",
+ "dWYuQW55Ei8KDm9wdGlvbmFsX3ZhbHVlGLICIAEoCzIWLmdvb2dsZS5wcm90",
+ "b2J1Zi5WYWx1ZRI1ChFyZXBlYXRlZF9kdXJhdGlvbhi3AiADKAsyGS5nb29n",
+ "bGUucHJvdG9idWYuRHVyYXRpb24SNwoScmVwZWF0ZWRfdGltZXN0YW1wGLgC",
+ "IAMoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASNwoScmVwZWF0ZWRf",
+ "ZmllbGRtYXNrGLkCIAMoCzIaLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2sS",
+ "MQoPcmVwZWF0ZWRfc3RydWN0GMQCIAMoCzIXLmdvb2dsZS5wcm90b2J1Zi5T",
+ "dHJ1Y3QSKwoMcmVwZWF0ZWRfYW55GLsCIAMoCzIULmdvb2dsZS5wcm90b2J1",
+ "Zi5BbnkSLwoOcmVwZWF0ZWRfdmFsdWUYvAIgAygLMhYuZ29vZ2xlLnByb3Rv",
+ "YnVmLlZhbHVlEhMKCmZpZWxkbmFtZTEYkQMgASgFEhQKC2ZpZWxkX25hbWUy",
+ "GJIDIAEoBRIVCgxfZmllbGRfbmFtZTMYkwMgASgFEhYKDWZpZWxkX19uYW1l",
+ "NF8YlAMgASgFEhQKC2ZpZWxkMG5hbWU1GJUDIAEoBRIWCg1maWVsZF8wX25h",
+ "bWU2GJYDIAEoBRITCgpmaWVsZE5hbWU3GJcDIAEoBRITCgpGaWVsZE5hbWU4",
+ "GJgDIAEoBRIUCgtmaWVsZF9OYW1lORiZAyABKAUSFQoMRmllbGRfTmFtZTEw",
+ "GJoDIAEoBRIVCgxGSUVMRF9OQU1FMTEYmwMgASgFEhUKDEZJRUxEX25hbWUx",
+ "MhicAyABKAUSFwoOX19maWVsZF9uYW1lMTMYnQMgASgFEhcKDl9fRmllbGRf",
+ "bmFtZTE0GJ4DIAEoBRIWCg1maWVsZF9fbmFtZTE1GJ8DIAEoBRIWCg1maWVs",
+ "ZF9fTmFtZTE2GKADIAEoBRIXCg5maWVsZF9uYW1lMTdfXxihAyABKAUSFwoO",
+ "RmllbGRfbmFtZTE4X18YogMgASgFGkoKDU5lc3RlZE1lc3NhZ2USCQoBYRgB",
+ "IAEoBRIuCgtjb3JlY3Vyc2l2ZRgCIAEoCzIZLmNvbmZvcm1hbmNlLlRlc3RB",
+ "bGxUeXBlcxo0ChJNYXBJbnQzMkludDMyRW50cnkSCwoDa2V5GAEgASgFEg0K",
+ "BXZhbHVlGAIgASgFOgI4ARo0ChJNYXBJbnQ2NEludDY0RW50cnkSCwoDa2V5",
+ "GAEgASgDEg0KBXZhbHVlGAIgASgDOgI4ARo2ChRNYXBVaW50MzJVaW50MzJF",
+ "bnRyeRILCgNrZXkYASABKA0SDQoFdmFsdWUYAiABKA06AjgBGjYKFE1hcFVp",
+ "bnQ2NFVpbnQ2NEVudHJ5EgsKA2tleRgBIAEoBBINCgV2YWx1ZRgCIAEoBDoC",
+ "OAEaNgoUTWFwU2ludDMyU2ludDMyRW50cnkSCwoDa2V5GAEgASgREg0KBXZh",
+ "bHVlGAIgASgROgI4ARo2ChRNYXBTaW50NjRTaW50NjRFbnRyeRILCgNrZXkY",
+ "ASABKBISDQoFdmFsdWUYAiABKBI6AjgBGjgKFk1hcEZpeGVkMzJGaXhlZDMy",
+ "RW50cnkSCwoDa2V5GAEgASgHEg0KBXZhbHVlGAIgASgHOgI4ARo4ChZNYXBG",
+ "aXhlZDY0Rml4ZWQ2NEVudHJ5EgsKA2tleRgBIAEoBhINCgV2YWx1ZRgCIAEo",
+ "BjoCOAEaOgoYTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5EgsKA2tleRgBIAEo",
+ "DxINCgV2YWx1ZRgCIAEoDzoCOAEaOgoYTWFwU2ZpeGVkNjRTZml4ZWQ2NEVu",
+ "dHJ5EgsKA2tleRgBIAEoEBINCgV2YWx1ZRgCIAEoEDoCOAEaNAoSTWFwSW50",
+ "MzJGbG9hdEVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoAjoCOAEa",
+ "NQoTTWFwSW50MzJEb3VibGVFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUY",
+ "AiABKAE6AjgBGjIKEE1hcEJvb2xCb29sRW50cnkSCwoDa2V5GAEgASgIEg0K",
+ "BXZhbHVlGAIgASgIOgI4ARo2ChRNYXBTdHJpbmdTdHJpbmdFbnRyeRILCgNr",
+ "ZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBGjUKE01hcFN0cmluZ0J5dGVz",
+ "RW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgMOgI4ARpmChtNYXBT",
+ "dHJpbmdOZXN0ZWRNZXNzYWdlRW50cnkSCwoDa2V5GAEgASgJEjYKBXZhbHVl",
+ "GAIgASgLMicuY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzLk5lc3RlZE1lc3Nh",
+ "Z2U6AjgBGlsKHE1hcFN0cmluZ0ZvcmVpZ25NZXNzYWdlRW50cnkSCwoDa2V5",
+ "GAEgASgJEioKBXZhbHVlGAIgASgLMhsuY29uZm9ybWFuY2UuRm9yZWlnbk1l",
+ "c3NhZ2U6AjgBGmAKGE1hcFN0cmluZ05lc3RlZEVudW1FbnRyeRILCgNrZXkY",
+ "ASABKAkSMwoFdmFsdWUYAiABKA4yJC5jb25mb3JtYW5jZS5UZXN0QWxsVHlw",
+ "ZXMuTmVzdGVkRW51bToCOAEaVQoZTWFwU3RyaW5nRm9yZWlnbkVudW1FbnRy",
+ "eRILCgNrZXkYASABKAkSJwoFdmFsdWUYAiABKA4yGC5jb25mb3JtYW5jZS5G",
+ "b3JlaWduRW51bToCOAEiOQoKTmVzdGVkRW51bRIHCgNGT08QABIHCgNCQVIQ",
+ "ARIHCgNCQVoQAhIQCgNORUcQ////////////AUINCgtvbmVvZl9maWVsZCIb",
+ "Cg5Gb3JlaWduTWVzc2FnZRIJCgFjGAEgASgFKjUKCldpcmVGb3JtYXQSDwoL",
+ "VU5TUEVDSUZJRUQQABIMCghQUk9UT0JVRhABEggKBEpTT04QAipACgtGb3Jl",
+ "aWduRW51bRIPCgtGT1JFSUdOX0ZPTxAAEg8KC0ZPUkVJR05fQkFSEAESDwoL",
+ "Rk9SRUlHTl9CQVoQAkIhCh9jb20uZ29vZ2xlLnByb3RvYnVmLmNvbmZvcm1h",
+ "bmNlYgZwcm90bzM="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.FieldMaskReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, },
new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Conformance.WireFormat), typeof(global::Conformance.ForeignEnum), }, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "RequestedOutputFormat" }, new[]{ "Payload" }, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceResponse), global::Conformance.ConformanceResponse.Parser, new[]{ "ParseError", "SerializeError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped" }, new[]{ "Result" }, null, null),
- new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.TestAllTypes), global::Conformance.TestAllTypes.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalStringPiece", "OptionalCord", "RecursiveMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapStringBytes", "MapStringNestedMessage", "MapStringForeignMessage", "MapStringNestedEnum", "MapStringForeignEnum", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", "OptionalBoolWrapper", "OptionalInt32Wrapper", "OptionalInt64Wrapper", "OptionalUint32Wrapper", "OptionalUint64Wrapper", "OptionalFloatWrapper", "OptionalDoubleWrapper", "OptionalStringWrapper", "OptionalBytesWrapper", "RepeatedBoolWrapper", "RepeatedInt32Wrapper", "RepeatedInt64Wrapper", "RepeatedUint32Wrapper", "RepeatedUint64Wrapper", "RepeatedFloatWrapper", "RepeatedDoubleWrapper", "RepeatedStringWrapper", "RepeatedBytesWrapper", "OptionalDuration", "OptionalTimestamp", "OptionalFieldMask", "OptionalStruct", "OptionalAny", "OptionalValue", "RepeatedDuration", "RepeatedTimestamp", "RepeatedFieldmask", "RepeatedStruct", "RepeatedAny", "RepeatedValue", "Fieldname1", "FieldName2", "FieldName3", "FieldName4", "Field0Name5", "Field0Name6", "FieldName7", "FieldName8", "FieldName9", "FieldName10", "FIELDNAME11", "FIELDName12" }, new[]{ "OneofField" }, new[]{ typeof(global::Conformance.TestAllTypes.Types.NestedEnum) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.TestAllTypes.Types.NestedMessage), global::Conformance.TestAllTypes.Types.NestedMessage.Parser, new[]{ "A", "Corecursive" }, null, null, null),
+ new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.TestAllTypes), global::Conformance.TestAllTypes.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalStringPiece", "OptionalCord", "RecursiveMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapStringBytes", "MapStringNestedMessage", "MapStringForeignMessage", "MapStringNestedEnum", "MapStringForeignEnum", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", "OneofBool", "OneofUint64", "OneofFloat", "OneofDouble", "OneofEnum", "OptionalBoolWrapper", "OptionalInt32Wrapper", "OptionalInt64Wrapper", "OptionalUint32Wrapper", "OptionalUint64Wrapper", "OptionalFloatWrapper", "OptionalDoubleWrapper", "OptionalStringWrapper", "OptionalBytesWrapper", "RepeatedBoolWrapper", "RepeatedInt32Wrapper", "RepeatedInt64Wrapper", "RepeatedUint32Wrapper", "RepeatedUint64Wrapper", "RepeatedFloatWrapper", "RepeatedDoubleWrapper", "RepeatedStringWrapper", "RepeatedBytesWrapper", "OptionalDuration", "OptionalTimestamp", "OptionalFieldMask", "OptionalStruct", "OptionalAny", "OptionalValue", "RepeatedDuration", "RepeatedTimestamp", "RepeatedFieldmask", "RepeatedStruct", "RepeatedAny", "RepeatedValue", "Fieldname1", "FieldName2", "FieldName3", "FieldName4", "Field0Name5", "Field0Name6", "FieldName7", "FieldName8", "FieldName9", "FieldName10", "FIELDNAME11", "FIELDName12", "FieldName13", "FieldName14", "FieldName15", "FieldName16", "FieldName17", "FieldName18" }, new[]{ "OneofField" }, new[]{ typeof(global::Conformance.TestAllTypes.Types.NestedEnum) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.TestAllTypes.Types.NestedMessage), global::Conformance.TestAllTypes.Types.NestedMessage.Parser, new[]{ "A", "Corecursive" }, null, null, null),
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }),
new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ForeignMessage), global::Conformance.ForeignMessage.Parser, new[]{ "C" }, null, null, null)
}));
@@ -890,6 +897,12 @@ namespace Conformance {
fieldName10_ = other.fieldName10_;
fIELDNAME11_ = other.fIELDNAME11_;
fIELDName12_ = other.fIELDName12_;
+ FieldName13_ = other.FieldName13_;
+ FieldName14_ = other.FieldName14_;
+ fieldName15_ = other.fieldName15_;
+ fieldName16_ = other.fieldName16_;
+ fieldName17_ = other.fieldName17_;
+ fieldName18_ = other.fieldName18_;
switch (other.OneofFieldCase) {
case OneofFieldOneofCase.OneofUint32:
OneofUint32 = other.OneofUint32;
@@ -903,6 +916,21 @@ namespace Conformance {
case OneofFieldOneofCase.OneofBytes:
OneofBytes = other.OneofBytes;
break;
+ case OneofFieldOneofCase.OneofBool:
+ OneofBool = other.OneofBool;
+ break;
+ case OneofFieldOneofCase.OneofUint64:
+ OneofUint64 = other.OneofUint64;
+ break;
+ case OneofFieldOneofCase.OneofFloat:
+ OneofFloat = other.OneofFloat;
+ break;
+ case OneofFieldOneofCase.OneofDouble:
+ OneofDouble = other.OneofDouble;
+ break;
+ case OneofFieldOneofCase.OneofEnum:
+ OneofEnum = other.OneofEnum;
+ break;
}
}
@@ -1607,6 +1635,61 @@ namespace Conformance {
}
}
+ /// <summary>Field number for the "oneof_bool" field.</summary>
+ public const int OneofBoolFieldNumber = 115;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public bool OneofBool {
+ get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBool ? (bool) oneofField_ : false; }
+ set {
+ oneofField_ = value;
+ oneofFieldCase_ = OneofFieldOneofCase.OneofBool;
+ }
+ }
+
+ /// <summary>Field number for the "oneof_uint64" field.</summary>
+ public const int OneofUint64FieldNumber = 116;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public ulong OneofUint64 {
+ get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint64 ? (ulong) oneofField_ : 0UL; }
+ set {
+ oneofField_ = value;
+ oneofFieldCase_ = OneofFieldOneofCase.OneofUint64;
+ }
+ }
+
+ /// <summary>Field number for the "oneof_float" field.</summary>
+ public const int OneofFloatFieldNumber = 117;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public float OneofFloat {
+ get { return oneofFieldCase_ == OneofFieldOneofCase.OneofFloat ? (float) oneofField_ : 0F; }
+ set {
+ oneofField_ = value;
+ oneofFieldCase_ = OneofFieldOneofCase.OneofFloat;
+ }
+ }
+
+ /// <summary>Field number for the "oneof_double" field.</summary>
+ public const int OneofDoubleFieldNumber = 118;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double OneofDouble {
+ get { return oneofFieldCase_ == OneofFieldOneofCase.OneofDouble ? (double) oneofField_ : 0D; }
+ set {
+ oneofField_ = value;
+ oneofFieldCase_ = OneofFieldOneofCase.OneofDouble;
+ }
+ }
+
+ /// <summary>Field number for the "oneof_enum" field.</summary>
+ public const int OneofEnumFieldNumber = 119;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public global::Conformance.TestAllTypes.Types.NestedEnum OneofEnum {
+ get { return oneofFieldCase_ == OneofFieldOneofCase.OneofEnum ? (global::Conformance.TestAllTypes.Types.NestedEnum) oneofField_ : 0; }
+ set {
+ oneofField_ = value;
+ oneofFieldCase_ = OneofFieldOneofCase.OneofEnum;
+ }
+ }
+
/// <summary>Field number for the "optional_bool_wrapper" field.</summary>
public const int OptionalBoolWrapperFieldNumber = 201;
private static readonly pb::FieldCodec<bool?> _single_optionalBoolWrapper_codec = pb::FieldCodec.ForStructWrapper<bool>(1610);
@@ -1939,6 +2022,7 @@ namespace Conformance {
private int fieldname1_;
/// <summary>
/// Test field-name-to-JSON-name convention.
+ /// (protobuf says names can be any valid C/C++ identifier.)
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int Fieldname1 {
@@ -2069,6 +2153,72 @@ namespace Conformance {
}
}
+ /// <summary>Field number for the "__field_name13" field.</summary>
+ public const int FieldName13FieldNumber = 413;
+ private int FieldName13_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int FieldName13 {
+ get { return FieldName13_; }
+ set {
+ FieldName13_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "__Field_name14" field.</summary>
+ public const int FieldName14FieldNumber = 414;
+ private int FieldName14_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int FieldName14 {
+ get { return FieldName14_; }
+ set {
+ FieldName14_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "field__name15" field.</summary>
+ public const int FieldName15FieldNumber = 415;
+ private int fieldName15_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int FieldName15 {
+ get { return fieldName15_; }
+ set {
+ fieldName15_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "field__Name16" field.</summary>
+ public const int FieldName16FieldNumber = 416;
+ private int fieldName16_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int FieldName16 {
+ get { return fieldName16_; }
+ set {
+ fieldName16_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "field_name17__" field.</summary>
+ public const int FieldName17FieldNumber = 417;
+ private int fieldName17_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int FieldName17 {
+ get { return fieldName17_; }
+ set {
+ fieldName17_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Field_name18__" field.</summary>
+ public const int FieldName18FieldNumber = 418;
+ private int fieldName18_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int FieldName18 {
+ get { return fieldName18_; }
+ set {
+ fieldName18_ = value;
+ }
+ }
+
private object oneofField_;
/// <summary>Enum of possible cases for the "oneof_field" oneof.</summary>
public enum OneofFieldOneofCase {
@@ -2077,6 +2227,11 @@ namespace Conformance {
OneofNestedMessage = 112,
OneofString = 113,
OneofBytes = 114,
+ OneofBool = 115,
+ OneofUint64 = 116,
+ OneofFloat = 117,
+ OneofDouble = 118,
+ OneofEnum = 119,
}
private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2169,6 +2324,11 @@ namespace Conformance {
if (!object.Equals(OneofNestedMessage, other.OneofNestedMessage)) return false;
if (OneofString != other.OneofString) return false;
if (OneofBytes != other.OneofBytes) return false;
+ if (OneofBool != other.OneofBool) return false;
+ if (OneofUint64 != other.OneofUint64) return false;
+ if (OneofFloat != other.OneofFloat) return false;
+ if (OneofDouble != other.OneofDouble) return false;
+ if (OneofEnum != other.OneofEnum) return false;
if (OptionalBoolWrapper != other.OptionalBoolWrapper) return false;
if (OptionalInt32Wrapper != other.OptionalInt32Wrapper) return false;
if (OptionalInt64Wrapper != other.OptionalInt64Wrapper) return false;
@@ -2211,6 +2371,12 @@ namespace Conformance {
if (FieldName10 != other.FieldName10) return false;
if (FIELDNAME11 != other.FIELDNAME11) return false;
if (FIELDName12 != other.FIELDName12) return false;
+ if (FieldName13 != other.FieldName13) return false;
+ if (FieldName14 != other.FieldName14) return false;
+ if (FieldName15 != other.FieldName15) return false;
+ if (FieldName16 != other.FieldName16) return false;
+ if (FieldName17 != other.FieldName17) return false;
+ if (FieldName18 != other.FieldName18) return false;
if (OneofFieldCase != other.OneofFieldCase) return false;
return true;
}
@@ -2284,6 +2450,11 @@ namespace Conformance {
if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode();
if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) hash ^= OneofString.GetHashCode();
if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) hash ^= OneofBytes.GetHashCode();
+ if (oneofFieldCase_ == OneofFieldOneofCase.OneofBool) hash ^= OneofBool.GetHashCode();
+ if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint64) hash ^= OneofUint64.GetHashCode();
+ if (oneofFieldCase_ == OneofFieldOneofCase.OneofFloat) hash ^= OneofFloat.GetHashCode();
+ if (oneofFieldCase_ == OneofFieldOneofCase.OneofDouble) hash ^= OneofDouble.GetHashCode();
+ if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) hash ^= OneofEnum.GetHashCode();
if (optionalBoolWrapper_ != null) hash ^= OptionalBoolWrapper.GetHashCode();
if (optionalInt32Wrapper_ != null) hash ^= OptionalInt32Wrapper.GetHashCode();
if (optionalInt64Wrapper_ != null) hash ^= OptionalInt64Wrapper.GetHashCode();
@@ -2326,6 +2497,12 @@ namespace Conformance {
if (FieldName10 != 0) hash ^= FieldName10.GetHashCode();
if (FIELDNAME11 != 0) hash ^= FIELDNAME11.GetHashCode();
if (FIELDName12 != 0) hash ^= FIELDName12.GetHashCode();
+ if (FieldName13 != 0) hash ^= FieldName13.GetHashCode();
+ if (FieldName14 != 0) hash ^= FieldName14.GetHashCode();
+ if (FieldName15 != 0) hash ^= FieldName15.GetHashCode();
+ if (FieldName16 != 0) hash ^= FieldName16.GetHashCode();
+ if (FieldName17 != 0) hash ^= FieldName17.GetHashCode();
+ if (FieldName18 != 0) hash ^= FieldName18.GetHashCode();
hash ^= (int) oneofFieldCase_;
return hash;
}
@@ -2481,6 +2658,26 @@ namespace Conformance {
output.WriteRawTag(146, 7);
output.WriteBytes(OneofBytes);
}
+ if (oneofFieldCase_ == OneofFieldOneofCase.OneofBool) {
+ output.WriteRawTag(152, 7);
+ output.WriteBool(OneofBool);
+ }
+ if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint64) {
+ output.WriteRawTag(160, 7);
+ output.WriteUInt64(OneofUint64);
+ }
+ if (oneofFieldCase_ == OneofFieldOneofCase.OneofFloat) {
+ output.WriteRawTag(173, 7);
+ output.WriteFloat(OneofFloat);
+ }
+ if (oneofFieldCase_ == OneofFieldOneofCase.OneofDouble) {
+ output.WriteRawTag(177, 7);
+ output.WriteDouble(OneofDouble);
+ }
+ if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) {
+ output.WriteRawTag(184, 7);
+ output.WriteEnum((int) OneofEnum);
+ }
if (optionalBoolWrapper_ != null) {
_single_optionalBoolWrapper_codec.WriteTagAndValue(output, OptionalBoolWrapper);
}
@@ -2595,6 +2792,30 @@ namespace Conformance {
output.WriteRawTag(224, 25);
output.WriteInt32(FIELDName12);
}
+ if (FieldName13 != 0) {
+ output.WriteRawTag(232, 25);
+ output.WriteInt32(FieldName13);
+ }
+ if (FieldName14 != 0) {
+ output.WriteRawTag(240, 25);
+ output.WriteInt32(FieldName14);
+ }
+ if (FieldName15 != 0) {
+ output.WriteRawTag(248, 25);
+ output.WriteInt32(FieldName15);
+ }
+ if (FieldName16 != 0) {
+ output.WriteRawTag(128, 26);
+ output.WriteInt32(FieldName16);
+ }
+ if (FieldName17 != 0) {
+ output.WriteRawTag(136, 26);
+ output.WriteInt32(FieldName17);
+ }
+ if (FieldName18 != 0) {
+ output.WriteRawTag(144, 26);
+ output.WriteInt32(FieldName18);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2718,6 +2939,21 @@ namespace Conformance {
if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) {
size += 2 + pb::CodedOutputStream.ComputeBytesSize(OneofBytes);
}
+ if (oneofFieldCase_ == OneofFieldOneofCase.OneofBool) {
+ size += 2 + 1;
+ }
+ if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint64) {
+ size += 2 + pb::CodedOutputStream.ComputeUInt64Size(OneofUint64);
+ }
+ if (oneofFieldCase_ == OneofFieldOneofCase.OneofFloat) {
+ size += 2 + 4;
+ }
+ if (oneofFieldCase_ == OneofFieldOneofCase.OneofDouble) {
+ size += 2 + 8;
+ }
+ if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) {
+ size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OneofEnum);
+ }
if (optionalBoolWrapper_ != null) {
size += _single_optionalBoolWrapper_codec.CalculateSizeWithTag(OptionalBoolWrapper);
}
@@ -2814,6 +3050,24 @@ namespace Conformance {
if (FIELDName12 != 0) {
size += 2 + pb::CodedOutputStream.ComputeInt32Size(FIELDName12);
}
+ if (FieldName13 != 0) {
+ size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName13);
+ }
+ if (FieldName14 != 0) {
+ size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName14);
+ }
+ if (FieldName15 != 0) {
+ size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName15);
+ }
+ if (FieldName16 != 0) {
+ size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName16);
+ }
+ if (FieldName17 != 0) {
+ size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName17);
+ }
+ if (FieldName18 != 0) {
+ size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName18);
+ }
return size;
}
@@ -3069,6 +3323,24 @@ namespace Conformance {
if (other.FIELDName12 != 0) {
FIELDName12 = other.FIELDName12;
}
+ if (other.FieldName13 != 0) {
+ FieldName13 = other.FieldName13;
+ }
+ if (other.FieldName14 != 0) {
+ FieldName14 = other.FieldName14;
+ }
+ if (other.FieldName15 != 0) {
+ FieldName15 = other.FieldName15;
+ }
+ if (other.FieldName16 != 0) {
+ FieldName16 = other.FieldName16;
+ }
+ if (other.FieldName17 != 0) {
+ FieldName17 = other.FieldName17;
+ }
+ if (other.FieldName18 != 0) {
+ FieldName18 = other.FieldName18;
+ }
switch (other.OneofFieldCase) {
case OneofFieldOneofCase.OneofUint32:
OneofUint32 = other.OneofUint32;
@@ -3082,6 +3354,21 @@ namespace Conformance {
case OneofFieldOneofCase.OneofBytes:
OneofBytes = other.OneofBytes;
break;
+ case OneofFieldOneofCase.OneofBool:
+ OneofBool = other.OneofBool;
+ break;
+ case OneofFieldOneofCase.OneofUint64:
+ OneofUint64 = other.OneofUint64;
+ break;
+ case OneofFieldOneofCase.OneofFloat:
+ OneofFloat = other.OneofFloat;
+ break;
+ case OneofFieldOneofCase.OneofDouble:
+ OneofDouble = other.OneofDouble;
+ break;
+ case OneofFieldOneofCase.OneofEnum:
+ OneofEnum = other.OneofEnum;
+ break;
}
}
@@ -3387,6 +3674,27 @@ namespace Conformance {
OneofBytes = input.ReadBytes();
break;
}
+ case 920: {
+ OneofBool = input.ReadBool();
+ break;
+ }
+ case 928: {
+ OneofUint64 = input.ReadUInt64();
+ break;
+ }
+ case 941: {
+ OneofFloat = input.ReadFloat();
+ break;
+ }
+ case 945: {
+ OneofDouble = input.ReadDouble();
+ break;
+ }
+ case 952: {
+ oneofField_ = input.ReadEnum();
+ oneofFieldCase_ = OneofFieldOneofCase.OneofEnum;
+ break;
+ }
case 1610: {
bool? value = _single_optionalBoolWrapper_codec.Read(input);
if (optionalBoolWrapper_ == null || value != false) {
@@ -3600,6 +3908,30 @@ namespace Conformance {
FIELDName12 = input.ReadInt32();
break;
}
+ case 3304: {
+ FieldName13 = input.ReadInt32();
+ break;
+ }
+ case 3312: {
+ FieldName14 = input.ReadInt32();
+ break;
+ }
+ case 3320: {
+ FieldName15 = input.ReadInt32();
+ break;
+ }
+ case 3328: {
+ FieldName16 = input.ReadInt32();
+ break;
+ }
+ case 3336: {
+ FieldName17 = input.ReadInt32();
+ break;
+ }
+ case 3344: {
+ FieldName18 = input.ReadInt32();
+ break;
+ }
}
}
}
diff --git a/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj b/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj
deleted file mode 100644
index 82f728d1..00000000
--- a/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProjectGuid>{0607D1B8-80D6-4B35-9857-1263C1B32B94}</ProjectGuid>
- <OutputType>Exe</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Google.Protobuf.Conformance</RootNamespace>
- <AssemblyName>Google.Protobuf.Conformance</AssemblyName>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <PlatformTarget>AnyCPU</PlatformTarget>
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <PlatformTarget>AnyCPU</PlatformTarget>
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="Microsoft.CSharp" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="Conformance.cs" />
- <Compile Include="Program.cs" />
- <Compile Include="Properties\AssemblyInfo.cs" />
- </ItemGroup>
- <ItemGroup>
- <None Include="App.config" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj">
- <Project>{6908bdce-d925-43f3-94ac-a531e6df2591}</Project>
- <Name>Google.Protobuf</Name>
- </ProjectReference>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project> \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.xproj b/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.xproj
new file mode 100644
index 00000000..99ff1465
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.xproj
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
+ <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
+ </PropertyGroup>
+ <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>dddc055b-e185-4181-bab0-072f0f984569</ProjectGuid>
+ <RootNamespace>Google.Protobuf.Conformance</RootNamespace>
+ <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
+ <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <SchemaVersion>2.0</SchemaVersion>
+ </PropertyGroup>
+ <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
+</Project> \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Conformance/project.json b/csharp/src/Google.Protobuf.Conformance/project.json
new file mode 100644
index 00000000..84b23c45
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Conformance/project.json
@@ -0,0 +1,19 @@
+{
+ "buildOptions": {
+ "debugType": "portable",
+ "emitEntryPoint": true
+ },
+ "dependencies": {
+ "Google.Protobuf": { "target": "project" }
+ },
+ "frameworks": {
+ "netcoreapp1.0": {
+ "dependencies": {
+ "Microsoft.NETCore.App": {
+ "type": "platform",
+ "version": "1.0.0"
+ }
+ }
+ }
+ }
+}
diff --git a/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj b/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj
deleted file mode 100644
index ede1f778..00000000
--- a/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.30729</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{D7282E99-2DC3-405B-946F-177DB2FD2AE2}</ProjectGuid>
- <OutputType>Exe</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Google.Protobuf.JsonDump</RootNamespace>
- <AssemblyName>Google.Protobuf.JsonDump</AssemblyName>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <TargetFrameworkProfile>
- </TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug</OutputPath>
- <IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <NoStdLib>true</NoStdLib>
- <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
- <Prefer32Bit>false</Prefer32Bit>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release</OutputPath>
- <IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <NoStdLib>true</NoStdLib>
- <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
- <Prefer32Bit>false</Prefer32Bit>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="mscorlib" />
- <Reference Include="System" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="Program.cs" />
- <Compile Include="Properties\AssemblyInfo.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj">
- <Project>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
- <Name>Google.Protobuf</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <None Include="app.config" />
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project> \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.xproj b/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.xproj
new file mode 100644
index 00000000..27095be5
--- /dev/null
+++ b/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.xproj
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
+ <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
+ </PropertyGroup>
+ <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>9695e08f-9829-497d-b95c-b38f28d48690</ProjectGuid>
+ <RootNamespace>Google.Protobuf.JsonDump</RootNamespace>
+ <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
+ <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <SchemaVersion>2.0</SchemaVersion>
+ </PropertyGroup>
+ <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
+</Project> \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.JsonDump/Program.cs b/csharp/src/Google.Protobuf.JsonDump/Program.cs
index 99e60e90..296b2f3f 100644
--- a/csharp/src/Google.Protobuf.JsonDump/Program.cs
+++ b/csharp/src/Google.Protobuf.JsonDump/Program.cs
@@ -32,6 +32,7 @@
using System;
using System.IO;
+using System.Reflection;
namespace Google.Protobuf.ProtoDump
{
@@ -55,7 +56,7 @@ namespace Google.Protobuf.ProtoDump
Console.Error.WriteLine("Unable to load type {0}.", args[0]);
return 1;
}
- if (!typeof(IMessage).IsAssignableFrom(type))
+ if (!typeof(IMessage).GetTypeInfo().IsAssignableFrom(type))
{
Console.Error.WriteLine("Type {0} doesn't implement IMessage.", args[0]);
return 1;
diff --git a/csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs b/csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs
deleted file mode 100644
index d980b013..00000000
--- a/csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-
-[assembly: AssemblyTitle("ProtoDump")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("ProtoDump")]
-[assembly: AssemblyCopyright("Copyright © 2015")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-[assembly: AssemblyVersion("3.0.0.0")]
-[assembly: AssemblyFileVersion("3.0.0.0")]
diff --git a/csharp/src/Google.Protobuf.JsonDump/app.config b/csharp/src/Google.Protobuf.JsonDump/app.config
deleted file mode 100644
index 51278a45..00000000
--- a/csharp/src/Google.Protobuf.JsonDump/app.config
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
-<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
diff --git a/csharp/src/Google.Protobuf.JsonDump/project.json b/csharp/src/Google.Protobuf.JsonDump/project.json
new file mode 100644
index 00000000..84b23c45
--- /dev/null
+++ b/csharp/src/Google.Protobuf.JsonDump/project.json
@@ -0,0 +1,19 @@
+{
+ "buildOptions": {
+ "debugType": "portable",
+ "emitEntryPoint": true
+ },
+ "dependencies": {
+ "Google.Protobuf": { "target": "project" }
+ },
+ "frameworks": {
+ "netcoreapp1.0": {
+ "dependencies": {
+ "Microsoft.NETCore.App": {
+ "type": "platform",
+ "version": "1.0.0"
+ }
+ }
+ }
+ }
+}
diff --git a/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs b/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs
index 8ed54cfb..6852f75f 100644
--- a/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs
+++ b/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs
@@ -75,10 +75,96 @@ namespace Google.Protobuf.Collections
}
[Test]
- public void Add_RepeatedField()
+ public void AddRange_SlowPath()
+ {
+ var list = new RepeatedField<string>();
+ list.AddRange(new[] { "foo", "bar" }.Select(x => x));
+ Assert.AreEqual(2, list.Count);
+ Assert.AreEqual("foo", list[0]);
+ Assert.AreEqual("bar", list[1]);
+ }
+
+ [Test]
+ public void AddRange_SlowPath_NullsProhibited_ReferenceType()
+ {
+ var list = new RepeatedField<string>();
+ // It's okay for this to throw ArgumentNullException if necessary.
+ // It's not ideal, but not awful.
+ Assert.Catch<ArgumentException>(() => list.AddRange(new[] { "foo", null }.Select(x => x)));
+ }
+
+ [Test]
+ public void AddRange_SlowPath_NullsProhibited_NullableValueType()
+ {
+ var list = new RepeatedField<int?>();
+ // It's okay for this to throw ArgumentNullException if necessary.
+ // It's not ideal, but not awful.
+ Assert.Catch<ArgumentException>(() => list.AddRange(new[] { 20, (int?)null }.Select(x => x)));
+ }
+
+ [Test]
+ public void AddRange_Optimized_NonNullableValueType()
+ {
+ var list = new RepeatedField<int>();
+ list.AddRange(new List<int> { 20, 30 });
+ Assert.AreEqual(2, list.Count);
+ Assert.AreEqual(20, list[0]);
+ Assert.AreEqual(30, list[1]);
+ }
+
+ [Test]
+ public void AddRange_Optimized_ReferenceType()
+ {
+ var list = new RepeatedField<string>();
+ list.AddRange(new List<string> { "foo", "bar" });
+ Assert.AreEqual(2, list.Count);
+ Assert.AreEqual("foo", list[0]);
+ Assert.AreEqual("bar", list[1]);
+ }
+
+ [Test]
+ public void AddRange_Optimized_NullableValueType()
+ {
+ var list = new RepeatedField<int?>();
+ list.AddRange(new List<int?> { 20, 30 });
+ Assert.AreEqual(2, list.Count);
+ Assert.AreEqual((int?) 20, list[0]);
+ Assert.AreEqual((int?) 30, list[1]);
+ }
+
+ [Test]
+ public void AddRange_Optimized_NullsProhibited_ReferenceType()
+ {
+ // We don't just trust that a collection with a nullable element type doesn't contain nulls
+ var list = new RepeatedField<string>();
+ // It's okay for this to throw ArgumentNullException if necessary.
+ // It's not ideal, but not awful.
+ Assert.Catch<ArgumentException>(() => list.AddRange(new List<string> { "foo", null }));
+ }
+
+ [Test]
+ public void AddRange_Optimized_NullsProhibited_NullableValueType()
+ {
+ // We don't just trust that a collection with a nullable element type doesn't contain nulls
+ var list = new RepeatedField<int?>();
+ // It's okay for this to throw ArgumentNullException if necessary.
+ // It's not ideal, but not awful.
+ Assert.Catch<ArgumentException>(() => list.AddRange(new List<int?> { 20, null }));
+ }
+
+ [Test]
+ public void AddRange_AlreadyNotEmpty()
+ {
+ var list = new RepeatedField<int> { 1, 2, 3 };
+ list.AddRange(new List<int> { 4, 5, 6 });
+ CollectionAssert.AreEqual(new[] { 1, 2, 3, 4, 5, 6 }, list);
+ }
+
+ [Test]
+ public void AddRange_RepeatedField()
{
var list = new RepeatedField<string> { "original" };
- list.Add(new RepeatedField<string> { "foo", "bar" });
+ list.AddRange(new RepeatedField<string> { "foo", "bar" });
Assert.AreEqual(3, list.Count);
Assert.AreEqual("original", list[0]);
Assert.AreEqual("foo", list[1]);
diff --git a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs
index c616470e..0e2bad59 100644
--- a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs
+++ b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs
@@ -32,6 +32,7 @@
using System.Collections.Generic;
using System.IO;
+using System.Reflection;
using Google.Protobuf.TestProtos;
using NUnit.Framework;
@@ -162,7 +163,7 @@ namespace Google.Protobuf
codedOutput.Flush();
Assert.AreEqual(0, stream.Position);
Assert.AreEqual(0, codec.CalculateSizeWithTag(codec.DefaultValue));
- if (typeof(T).IsValueType)
+ if (typeof(T).GetTypeInfo().IsValueType)
{
Assert.AreEqual(default(T), codec.DefaultValue);
}
diff --git a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
deleted file mode 100644
index 4f37c5e2..00000000
--- a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
+++ /dev/null
@@ -1,143 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.30729</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{DD01ED24-3750-4567-9A23-1DB676A15610}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Google.Protobuf</RootNamespace>
- <AssemblyName>Google.Protobuf.Test</AssemblyName>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <OldToolsVersion>3.5</OldToolsVersion>
- <TargetFrameworkProfile>
- </TargetFrameworkProfile>
- <NuGetPackageImportStamp>
- </NuGetPackageImportStamp>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug</OutputPath>
- <IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
- <DefineConstants>DEBUG;TRACE;$(EnvironmentFlavor);$(EnvironmentTemplate)</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <NoStdLib>true</NoStdLib>
- <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
- <Prefer32Bit>false</Prefer32Bit>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release</OutputPath>
- <IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
- <DefineConstants>TRACE;$(EnvironmentFlavor);$(EnvironmentTemplate)</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <NoStdLib>true</NoStdLib>
- <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
- <Prefer32Bit>false</Prefer32Bit>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\ReleaseSigned</OutputPath>
- <IntermediateOutputPath>obj\ReleaseSigned\</IntermediateOutputPath>
- <DefineConstants>TRACE;$(EnvironmentFlavor);$(EnvironmentTemplate)</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <NoStdLib>true</NoStdLib>
- <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
- <Prefer32Bit>false</Prefer32Bit>
- <SignAssembly>True</SignAssembly>
- <AssemblyOriginatorKeyFile>..\..\keys\Google.Protobuf.snk</AssemblyOriginatorKeyFile>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="mscorlib" />
- <Reference Include="nunit.core, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
- <HintPath>..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.dll</HintPath>
- <Private>True</Private>
- </Reference>
- <Reference Include="nunit.core.interfaces, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
- <HintPath>..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.interfaces.dll</HintPath>
- <Private>True</Private>
- </Reference>
- <Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
- <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
- <Private>True</Private>
- </Reference>
- <Reference Include="nunit.util, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
- <HintPath>..\packages\NUnitTestAdapter.2.0.0\lib\nunit.util.dll</HintPath>
- <Private>True</Private>
- </Reference>
- <Reference Include="NUnit.VisualStudio.TestAdapter, Version=2.0.0.0, Culture=neutral, PublicKeyToken=4cb40d35494691ac, processorArchitecture=MSIL">
- <HintPath>..\packages\NUnitTestAdapter.2.0.0\lib\NUnit.VisualStudio.TestAdapter.dll</HintPath>
- <Private>True</Private>
- </Reference>
- <Reference Include="System" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="ByteStringTest.cs" />
- <Compile Include="CodedInputStreamExtensions.cs" />
- <Compile Include="CodedInputStreamTest.cs" />
- <Compile Include="CodedOutputStreamTest.cs" />
- <Compile Include="Compatibility\PropertyInfoExtensionsTest.cs" />
- <Compile Include="Compatibility\TypeExtensionsTest.cs" />
- <Compile Include="EqualityTester.cs" />
- <Compile Include="FieldCodecTest.cs" />
- <Compile Include="GeneratedMessageTest.cs" />
- <Compile Include="Collections\MapFieldTest.cs" />
- <Compile Include="Collections\RepeatedFieldTest.cs" />
- <Compile Include="JsonFormatterTest.cs" />
- <Compile Include="JsonParserTest.cs" />
- <Compile Include="JsonTokenizerTest.cs" />
- <Compile Include="Reflection\DescriptorsTest.cs" />
- <Compile Include="Reflection\FieldAccessTest.cs" />
- <Compile Include="Reflection\TypeRegistryTest.cs" />
- <Compile Include="SampleEnum.cs" />
- <Compile Include="SampleMessages.cs" />
- <Compile Include="TestProtos\ForeignMessagePartial.cs" />
- <Compile Include="TestProtos\MapUnittestProto3.cs" />
- <Compile Include="TestProtos\UnittestImportProto3.cs" />
- <Compile Include="TestProtos\UnittestImportPublicProto3.cs" />
- <Compile Include="TestProtos\UnittestIssues.cs" />
- <Compile Include="TestProtos\UnittestProto3.cs" />
- <Compile Include="DeprecatedMemberTest.cs" />
- <Compile Include="IssuesTest.cs" />
- <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\FieldMaskTest.cs" />
- <Compile Include="WellKnownTypes\TimestampTest.cs" />
- <Compile Include="WellKnownTypes\WrappersTest.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj">
- <Project>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
- <Name>Google.Protobuf</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <None Include="packages.config" />
- </ItemGroup>
- <ItemGroup>
- <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
- </ItemGroup>
- <ItemGroup />
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project> \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.xproj b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.xproj
new file mode 100644
index 00000000..a9a1cc04
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.xproj
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
+ <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
+ </PropertyGroup>
+ <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>580eb013-d3c7-4578-b845-015f4a3b0591</ProjectGuid>
+ <RootNamespace>Google.Protobuf.Test</RootNamespace>
+ <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
+ <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <SchemaVersion>2.0</SchemaVersion>
+ </PropertyGroup>
+ <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
+</Project> \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
index 51b3ca2d..261ac6a7 100644
--- a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
+++ b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
@@ -230,6 +230,12 @@ namespace Google.Protobuf
[TestCase("foo_bar", "fooBar")]
[TestCase("bananaBanana", "bananaBanana")]
[TestCase("BANANABanana", "bananaBanana")]
+ [TestCase("simple", "simple")]
+ [TestCase("ACTION_AND_ADVENTURE", "actionAndAdventure")]
+ [TestCase("action_and_adventure", "actionAndAdventure")]
+ [TestCase("kFoo", "kFoo")]
+ [TestCase("HTTPServer", "httpServer")]
+ [TestCase("CLIENT", "client")]
public void ToCamelCase(string original, string expected)
{
Assert.AreEqual(expected, JsonFormatter.ToCamelCase(original));
diff --git a/csharp/src/Google.Protobuf.Test/Properties/AppManifest.xml b/csharp/src/Google.Protobuf.Test/Properties/AppManifest.xml
deleted file mode 100644
index a9552327..00000000
--- a/csharp/src/Google.Protobuf.Test/Properties/AppManifest.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
->
- <Deployment.Parts>
- </Deployment.Parts>
-</Deployment>
diff --git a/csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs b/csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs
deleted file mode 100644
index d00acf85..00000000
--- a/csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-
-[assembly: AssemblyTitle("Google.Protobuf.Test")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Google.Protobuf.Test")]
-[assembly: AssemblyCopyright("Copyright © 2015")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-[assembly: AssemblyVersion("3.0.0.0")]
-[assembly: AssemblyFileVersion("3.0.0.0")]
diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
index f21be7d9..4aecc998 100644
--- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
+++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
@@ -96,7 +96,7 @@ namespace Google.Protobuf.WellKnownTypes
var message = SampleMessages.CreateFullTestAllTypes();
var any = Any.Pack(message);
var text = any.ToString();
- Assert.That(text, Is.StringContaining("\"@value\": \"" + message.ToByteString().ToBase64() + "\""));
+ Assert.That(text, Does.Contain("\"@value\": \"" + message.ToByteString().ToBase64() + "\""));
}
[Test]
diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs
index 89bc8275..1d9908b4 100644
--- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs
+++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs
@@ -46,8 +46,8 @@ namespace Google.Protobuf.WellKnownTypes
var mask = new FieldMask { Paths = { input } };
var text = mask.ToString();
// More specific test below
- Assert.That(text, Is.StringContaining("@warning"));
- Assert.That(text, Is.StringContaining(input));
+ Assert.That(text, Does.Contain("@warning"));
+ Assert.That(text, Does.Contain(input));
}
[Test]
diff --git a/csharp/src/Google.Protobuf.Test/packages.config b/csharp/src/Google.Protobuf.Test/packages.config
deleted file mode 100644
index c7653992..00000000
--- a/csharp/src/Google.Protobuf.Test/packages.config
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
- <package id="NUnit" version="2.6.4" targetFramework="net45" userInstalled="true" />
- <package id="NUnitTestAdapter" version="2.0.0" targetFramework="net45" userInstalled="true" />
-</packages> \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Test/project.json b/csharp/src/Google.Protobuf.Test/project.json
new file mode 100644
index 00000000..87b732c9
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Test/project.json
@@ -0,0 +1,44 @@
+{
+ "buildOptions": {
+ "debugType": "portable",
+ "keyFile": "../../keys/Google.Protobuf.snk"
+ },
+
+ "configurations": {
+ "Debug": {
+ "buildOptions": {
+ "define": [ "DEBUG", "TRACE" ]
+ }
+ },
+ "Release": {
+ "buildOptions": {
+ "define": [ "RELEASE", "TRACE" ],
+ "optimize": true
+ }
+ }
+ },
+
+ "dependencies": {
+ "Google.Protobuf": { "target": "project" },
+ "NUnit": "3.4.0",
+ "dotnet-test-nunit": "3.4.0-alpha-2",
+ },
+
+ "testRunner": "nunit",
+
+ "frameworks": {
+ "netcoreapp1.0": {
+ "imports" : [ "dnxcore50", "netcoreapp1.0", "portable-net45+win8" ],
+ "buildOptions": {
+ "define": [ "PCL" ]
+ },
+ "dependencies": {
+ "Microsoft.NETCore.App": {
+ "version": "1.0.0",
+ "type": "platform"
+ },
+ "System.Console": "4.0.0"
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.sln b/csharp/src/Google.Protobuf.sln
index 72d87f76..3c62bba3 100644
--- a/csharp/src/Google.Protobuf.sln
+++ b/csharp/src/Google.Protobuf.sln
@@ -1,54 +1,43 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2015
-VisualStudioVersion = 14.0.24720.0
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 14.0.24720.0
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf", "Google.Protobuf\Google.Protobuf.csproj", "{6908BDCE-D925-43F3-94AC-A531E6DF2591}"
+Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AddressBook", "AddressBook\AddressBook.xproj", "{AFB63919-1E05-43B4-802A-8FB8C9B2F463}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.Test", "Google.Protobuf.Test\Google.Protobuf.Test.csproj", "{DD01ED24-3750-4567-9A23-1DB676A15610}"
+Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Google.Protobuf", "Google.Protobuf\Google.Protobuf.xproj", "{9B576380-726D-4142-8238-60A43AB0E35A}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddressBook", "AddressBook\AddressBook.csproj", "{A31F5FB2-4FF3-432A-B35B-5CD203606311}"
+Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Google.Protobuf.Test", "Google.Protobuf.Test\Google.Protobuf.Test.xproj", "{580EB013-D3C7-4578-B845-015F4A3B0591}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.JsonDump", "Google.Protobuf.JsonDump\Google.Protobuf.JsonDump.csproj", "{D7282E99-2DC3-405B-946F-177DB2FD2AE2}"
+Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Google.Protobuf.Conformance", "Google.Protobuf.Conformance\Google.Protobuf.Conformance.xproj", "{DDDC055B-E185-4181-BAB0-072F0F984569}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.Conformance", "Google.Protobuf.Conformance\Google.Protobuf.Conformance.csproj", "{0607D1B8-80D6-4B35-9857-1263C1B32B94}"
+Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Google.Protobuf.JsonDump", "Google.Protobuf.JsonDump\Google.Protobuf.JsonDump.xproj", "{9695E08F-9829-497D-B95C-B38F28D48690}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
- ReleaseSigned|Any CPU = ReleaseSigned|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {6908BDCE-D925-43F3-94AC-A531E6DF2591}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {6908BDCE-D925-43F3-94AC-A531E6DF2591}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {6908BDCE-D925-43F3-94AC-A531E6DF2591}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {6908BDCE-D925-43F3-94AC-A531E6DF2591}.Release|Any CPU.Build.0 = Release|Any CPU
- {6908BDCE-D925-43F3-94AC-A531E6DF2591}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
- {6908BDCE-D925-43F3-94AC-A531E6DF2591}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
- {DD01ED24-3750-4567-9A23-1DB676A15610}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {DD01ED24-3750-4567-9A23-1DB676A15610}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {DD01ED24-3750-4567-9A23-1DB676A15610}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {DD01ED24-3750-4567-9A23-1DB676A15610}.Release|Any CPU.Build.0 = Release|Any CPU
- {DD01ED24-3750-4567-9A23-1DB676A15610}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
- {DD01ED24-3750-4567-9A23-1DB676A15610}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
- {A31F5FB2-4FF3-432A-B35B-5CD203606311}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A31F5FB2-4FF3-432A-B35B-5CD203606311}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A31F5FB2-4FF3-432A-B35B-5CD203606311}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A31F5FB2-4FF3-432A-B35B-5CD203606311}.Release|Any CPU.Build.0 = Release|Any CPU
- {A31F5FB2-4FF3-432A-B35B-5CD203606311}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
- {A31F5FB2-4FF3-432A-B35B-5CD203606311}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
- {D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Release|Any CPU.Build.0 = Release|Any CPU
- {D7282E99-2DC3-405B-946F-177DB2FD2AE2}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
- {D7282E99-2DC3-405B-946F-177DB2FD2AE2}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
- {0607D1B8-80D6-4B35-9857-1263C1B32B94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {0607D1B8-80D6-4B35-9857-1263C1B32B94}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {0607D1B8-80D6-4B35-9857-1263C1B32B94}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {0607D1B8-80D6-4B35-9857-1263C1B32B94}.Release|Any CPU.Build.0 = Release|Any CPU
- {0607D1B8-80D6-4B35-9857-1263C1B32B94}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
- {0607D1B8-80D6-4B35-9857-1263C1B32B94}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
+ {AFB63919-1E05-43B4-802A-8FB8C9B2F463}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AFB63919-1E05-43B4-802A-8FB8C9B2F463}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AFB63919-1E05-43B4-802A-8FB8C9B2F463}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AFB63919-1E05-43B4-802A-8FB8C9B2F463}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9B576380-726D-4142-8238-60A43AB0E35A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9B576380-726D-4142-8238-60A43AB0E35A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9B576380-726D-4142-8238-60A43AB0E35A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9B576380-726D-4142-8238-60A43AB0E35A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {580EB013-D3C7-4578-B845-015F4A3B0591}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {580EB013-D3C7-4578-B845-015F4A3B0591}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {580EB013-D3C7-4578-B845-015F4A3B0591}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {580EB013-D3C7-4578-B845-015F4A3B0591}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DDDC055B-E185-4181-BAB0-072F0F984569}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DDDC055B-E185-4181-BAB0-072F0F984569}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DDDC055B-E185-4181-BAB0-072F0F984569}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DDDC055B-E185-4181-BAB0-072F0F984569}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9695E08F-9829-497D-B95C-B38F28D48690}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9695E08F-9829-497D-B95C-B38F28D48690}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9695E08F-9829-497D-B95C-B38F28D48690}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9695E08F-9829-497D-B95C-B38F28D48690}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/csharp/src/Google.Protobuf/CodedInputStream.cs b/csharp/src/Google.Protobuf/CodedInputStream.cs
index ce6856d6..072e2e17 100644
--- a/csharp/src/Google.Protobuf/CodedInputStream.cs
+++ b/csharp/src/Google.Protobuf/CodedInputStream.cs
@@ -612,9 +612,7 @@ namespace Google.Protobuf
}
/// <summary>
- /// Reads an enum field value from the stream. If the enum is valid for type T,
- /// then the ref value is set and it returns true. Otherwise the unknown output
- /// value is set and this method returns false.
+ /// Reads an enum field value from the stream.
/// </summary>
public int ReadEnum()
{
diff --git a/csharp/src/Google.Protobuf/Collections/MapField.cs b/csharp/src/Google.Protobuf/Collections/MapField.cs
index 053f7558..537ce261 100644
--- a/csharp/src/Google.Protobuf/Collections/MapField.cs
+++ b/csharp/src/Google.Protobuf/Collections/MapField.cs
@@ -30,14 +30,13 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
+using Google.Protobuf.Compatibility;
using Google.Protobuf.Reflection;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using System.Text;
-using Google.Protobuf.Compatibility;
namespace Google.Protobuf.Collections
{
@@ -113,7 +112,7 @@ namespace Google.Protobuf.Collections
// Validation of arguments happens in ContainsKey and the indexer
if (ContainsKey(key))
{
- throw new ArgumentException("Key already exists in map", "key");
+ throw new ArgumentException("Key already exists in map", nameof(key));
}
this[key] = value;
}
@@ -125,7 +124,7 @@ namespace Google.Protobuf.Collections
/// <returns><c>true</c> if the map contains the given key; <c>false</c> otherwise.</returns>
public bool ContainsKey(TKey key)
{
- ProtoPreconditions.CheckNotNullUnconstrained(key, "key");
+ ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key));
return map.ContainsKey(key);
}
@@ -142,7 +141,7 @@ namespace Google.Protobuf.Collections
/// <returns><c>true</c> if the map contained the given key before the entry was removed; <c>false</c> otherwise.</returns>
public bool Remove(TKey key)
{
- ProtoPreconditions.CheckNotNullUnconstrained(key, "key");
+ ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key));
LinkedListNode<KeyValuePair<TKey, TValue>> node;
if (map.TryGetValue(key, out node))
{
@@ -190,7 +189,7 @@ namespace Google.Protobuf.Collections
{
get
{
- ProtoPreconditions.CheckNotNullUnconstrained(key, "key");
+ ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key));
TValue value;
if (TryGetValue(key, out value))
{
@@ -200,11 +199,11 @@ namespace Google.Protobuf.Collections
}
set
{
- ProtoPreconditions.CheckNotNullUnconstrained(key, "key");
+ ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key));
// value == null check here is redundant, but avoids boxing.
if (value == null)
{
- ProtoPreconditions.CheckNotNullUnconstrained(value, "value");
+ ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value));
}
LinkedListNode<KeyValuePair<TKey, TValue>> node;
var pair = new KeyValuePair<TKey, TValue>(key, value);
@@ -236,7 +235,7 @@ namespace Google.Protobuf.Collections
/// <param name="entries">The entries to add to the map.</param>
public void Add(IDictionary<TKey, TValue> entries)
{
- ProtoPreconditions.CheckNotNull(entries, "entries");
+ ProtoPreconditions.CheckNotNull(entries, nameof(entries));
foreach (var pair in entries)
{
Add(pair.Key, pair.Value);
@@ -315,7 +314,7 @@ namespace Google.Protobuf.Collections
{
if (item.Key == null)
{
- throw new ArgumentException("Key is null", "item");
+ throw new ArgumentException("Key is null", nameof(item));
}
LinkedListNode<KeyValuePair<TKey, TValue>> node;
if (map.TryGetValue(item.Key, out node) &&
@@ -503,7 +502,7 @@ namespace Google.Protobuf.Collections
void IDictionary.Remove(object key)
{
- ProtoPreconditions.CheckNotNull(key, "key");
+ ProtoPreconditions.CheckNotNull(key, nameof(key));
if (!(key is TKey))
{
return;
@@ -532,7 +531,7 @@ namespace Google.Protobuf.Collections
{
get
{
- ProtoPreconditions.CheckNotNull(key, "key");
+ ProtoPreconditions.CheckNotNull(key, nameof(key));
if (!(key is TKey))
{
return null;
@@ -714,11 +713,11 @@ namespace Google.Protobuf.Collections
{
if (arrayIndex < 0)
{
- throw new ArgumentOutOfRangeException("arrayIndex");
+ throw new ArgumentOutOfRangeException(nameof(arrayIndex));
}
if (arrayIndex + Count >= array.Length)
{
- throw new ArgumentException("Not enough space in the array", "array");
+ throw new ArgumentException("Not enough space in the array", nameof(array));
}
foreach (var item in this)
{
@@ -745,11 +744,11 @@ namespace Google.Protobuf.Collections
{
if (index < 0)
{
- throw new ArgumentOutOfRangeException("index");
+ throw new ArgumentOutOfRangeException(nameof(index));
}
if (index + Count >= array.Length)
{
- throw new ArgumentException("Not enough space in the array", "array");
+ throw new ArgumentException("Not enough space in the array", nameof(array));
}
foreach (var item in this)
{
diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
index d1db856c..7bb56448 100644
--- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
+++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
@@ -34,7 +34,6 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
-using System.Text;
namespace Google.Protobuf.Collections
{
@@ -227,10 +226,7 @@ namespace Google.Protobuf.Collections
/// <param name="item">The item to add.</param>
public void Add(T item)
{
- if (item == null)
- {
- throw new ArgumentNullException("item");
- }
+ ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item));
EnsureSize(count + 1);
array[count++] = item;
}
@@ -285,46 +281,82 @@ namespace Google.Protobuf.Collections
/// <summary>
/// Gets the number of elements contained in the collection.
/// </summary>
- public int Count { get { return count; } }
+ public int Count => count;
/// <summary>
/// Gets a value indicating whether the collection is read-only.
/// </summary>
- public bool IsReadOnly { get { return false; } }
-
- // TODO: Remove this overload and just handle it in the one below, at execution time?
+ public bool IsReadOnly => false;
/// <summary>
/// Adds all of the specified values into this collection.
/// </summary>
/// <param name="values">The values to add to this collection.</param>
- public void Add(RepeatedField<T> values)
+ public void AddRange(IEnumerable<T> values)
{
- if (values == null)
+ ProtoPreconditions.CheckNotNull(values, nameof(values));
+
+ // Optimization 1: If the collection we're adding is already a RepeatedField<T>,
+ // we know the values are valid.
+ var otherRepeatedField = values as RepeatedField<T>;
+ if (otherRepeatedField != null)
{
- throw new ArgumentNullException("values");
+ EnsureSize(count + otherRepeatedField.count);
+ Array.Copy(otherRepeatedField.array, 0, array, count, otherRepeatedField.count);
+ count += otherRepeatedField.count;
+ return;
+ }
+
+ // Optimization 2: The collection is an ICollection, so we can expand
+ // just once and ask the collection to copy itself into the array.
+ var collection = values as ICollection;
+ if (collection != null)
+ {
+ var extraCount = collection.Count;
+ // For reference types and nullable value types, we need to check that there are no nulls
+ // present. (This isn't a thread-safe approach, but we don't advertise this is thread-safe.)
+ // We expect the JITter to optimize this test to true/false, so it's effectively conditional
+ // specialization.
+ if (default(T) == null)
+ {
+ // TODO: Measure whether iterating once to check and then letting the collection copy
+ // itself is faster or slower than iterating and adding as we go. For large
+ // collections this will not be great in terms of cache usage... but the optimized
+ // copy may be significantly faster than doing it one at a time.
+ foreach (var item in collection)
+ {
+ if (item == null)
+ {
+ throw new ArgumentException("Sequence contained null element", nameof(values));
+ }
+ }
+ }
+ EnsureSize(count + extraCount);
+ collection.CopyTo(array, count);
+ count += extraCount;
+ return;
+ }
+
+ // We *could* check for ICollection<T> as well, but very very few collections implement
+ // ICollection<T> but not ICollection. (HashSet<T> does, for one...)
+
+ // Fall back to a slower path of adding items one at a time.
+ foreach (T item in values)
+ {
+ Add(item);
}
- EnsureSize(count + values.count);
- // We know that all the values will be valid, because it's a RepeatedField.
- Array.Copy(values.array, 0, array, count, values.count);
- count += values.count;
}
/// <summary>
- /// Adds all of the specified values into this collection.
+ /// Adds all of the specified values into this collection. This method is present to
+ /// allow repeated fields to be constructed from queries within collection initializers.
+ /// Within non-collection-initializer code, consider using the equivalent <see cref="AddRange"/>
+ /// method instead for clarity.
/// </summary>
/// <param name="values">The values to add to this collection.</param>
public void Add(IEnumerable<T> values)
{
- if (values == null)
- {
- throw new ArgumentNullException("values");
- }
- // TODO: Check for ICollection and get the Count, to optimize?
- foreach (T item in values)
- {
- Add(item);
- }
+ AddRange(values);
}
/// <summary>
@@ -418,10 +450,7 @@ namespace Google.Protobuf.Collections
/// <returns>The zero-based index of the item, or -1 if it is not found.</returns>
public int IndexOf(T item)
{
- if (item == null)
- {
- throw new ArgumentNullException("item");
- }
+ ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item));
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
for (int i = 0; i < count; i++)
{
@@ -440,13 +469,10 @@ namespace Google.Protobuf.Collections
/// <param name="item">The item to insert.</param>
public void Insert(int index, T item)
{
- if (item == null)
- {
- throw new ArgumentNullException("item");
- }
+ ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item));
if (index < 0 || index > count)
{
- throw new ArgumentOutOfRangeException("index");
+ throw new ArgumentOutOfRangeException(nameof(index));
}
EnsureSize(count + 1);
Array.Copy(array, index, array, index + 1, count - index);
@@ -462,7 +488,7 @@ namespace Google.Protobuf.Collections
{
if (index < 0 || index >= count)
{
- throw new ArgumentOutOfRangeException("index");
+ throw new ArgumentOutOfRangeException(nameof(index));
}
Array.Copy(array, index + 1, array, index, count - index - 1);
count--;
@@ -494,7 +520,7 @@ namespace Google.Protobuf.Collections
{
if (index < 0 || index >= count)
{
- throw new ArgumentOutOfRangeException("index");
+ throw new ArgumentOutOfRangeException(nameof(index));
}
return array[index];
}
@@ -502,27 +528,24 @@ namespace Google.Protobuf.Collections
{
if (index < 0 || index >= count)
{
- throw new ArgumentOutOfRangeException("index");
- }
- if (value == null)
- {
- throw new ArgumentNullException("value");
+ throw new ArgumentOutOfRangeException(nameof(index));
}
+ ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value));
array[index] = value;
}
}
#region Explicit interface implementation for IList and ICollection.
- bool IList.IsFixedSize { get { return false; } }
+ bool IList.IsFixedSize => false;
void ICollection.CopyTo(Array array, int index)
{
Array.Copy(this.array, 0, array, index, count);
}
- bool ICollection.IsSynchronized { get { return false; } }
+ bool ICollection.IsSynchronized => false;
- object ICollection.SyncRoot { get { return this; } }
+ object ICollection.SyncRoot => this;
object IList.this[int index]
{
diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
deleted file mode 100644
index 5557612a..00000000
--- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj
+++ /dev/null
@@ -1,168 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.30729</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Google.Protobuf</RootNamespace>
- <AssemblyName>Google.Protobuf</AssemblyName>
- <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
- <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <OldToolsVersion>3.5</OldToolsVersion>
- <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
- <NuGetPackageImportStamp>
- </NuGetPackageImportStamp>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug</OutputPath>
- <IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
- <DocumentationFile>bin\Debug\Google.Protobuf.xml</DocumentationFile>
- <NoWarn>
- </NoWarn>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <NoStdLib>true</NoStdLib>
- <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release</OutputPath>
- <IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
- <DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
- <NoWarn>
- </NoWarn>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <NoStdLib>true</NoStdLib>
- <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\ReleaseSigned</OutputPath>
- <IntermediateOutputPath>obj\ReleaseSigned\</IntermediateOutputPath>
- <DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
- <NoWarn>
- </NoWarn>
- <DefineConstants>TRACE;SIGNED</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <NoStdLib>true</NoStdLib>
- <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
- <SignAssembly>True</SignAssembly>
- <AssemblyOriginatorKeyFile>..\..\keys\Google.Protobuf.snk</AssemblyOriginatorKeyFile>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="mscorlib" />
- <Reference Include="System" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="ByteArray.cs" />
- <Compile Include="ByteString.cs" />
- <Compile Include="CodedOutputStream.ComputeSize.cs" />
- <Compile Include="CodedInputStream.cs" />
- <Compile Include="CodedOutputStream.cs" />
- <Compile Include="Collections\MapField.cs" />
- <Compile Include="Collections\ReadOnlyDictionary.cs" />
- <Compile Include="Collections\RepeatedField.cs" />
- <Compile Include="Compatibility\PropertyInfoExtensions.cs" />
- <Compile Include="Compatibility\TypeExtensions.cs" />
- <Compile Include="FieldCodec.cs" />
- <Compile Include="FrameworkPortability.cs" />
- <Compile Include="ICustomDiagnosticMessage.cs" />
- <Compile Include="IDeepCloneable.cs" />
- <Compile Include="InvalidJsonException.cs" />
- <Compile Include="JsonFormatter.cs" />
- <Compile Include="JsonParser.cs" />
- <Compile Include="JsonToken.cs" />
- <Compile Include="JsonTokenizer.cs" />
- <Compile Include="MessageExtensions.cs" />
- <Compile Include="IMessage.cs" />
- <Compile Include="InvalidProtocolBufferException.cs" />
- <Compile Include="LimitedInputStream.cs" />
- <Compile Include="MessageParser.cs" />
- <Compile Include="Properties\AssemblyInfo.cs" />
- <Compile Include="Reflection\Descriptor.cs" />
- <Compile Include="Reflection\DescriptorBase.cs" />
- <Compile Include="Reflection\DescriptorPool.cs" />
- <Compile Include="Reflection\DescriptorUtil.cs" />
- <Compile Include="Reflection\DescriptorValidationException.cs" />
- <Compile Include="Reflection\EnumDescriptor.cs" />
- <Compile Include="Reflection\EnumValueDescriptor.cs" />
- <Compile Include="Reflection\FieldAccessorBase.cs" />
- <Compile Include="Reflection\FieldDescriptor.cs" />
- <Compile Include="Reflection\FieldType.cs" />
- <Compile Include="Reflection\FileDescriptor.cs" />
- <Compile Include="Reflection\GeneratedClrTypeInfo.cs" />
- <Compile Include="Reflection\IDescriptor.cs" />
- <Compile Include="Reflection\IFieldAccessor.cs" />
- <Compile Include="Reflection\MapFieldAccessor.cs" />
- <Compile Include="Reflection\MessageDescriptor.cs" />
- <Compile Include="Reflection\MethodDescriptor.cs" />
- <Compile Include="Reflection\OneofAccessor.cs" />
- <Compile Include="Reflection\OneofDescriptor.cs" />
- <Compile Include="Reflection\OriginalNameAttribute.cs" />
- <Compile Include="Reflection\PackageDescriptor.cs" />
- <Compile Include="Reflection\PartialClasses.cs" />
- <Compile Include="Reflection\ReflectionUtil.cs" />
- <Compile Include="Reflection\RepeatedFieldAccessor.cs" />
- <Compile Include="Reflection\ServiceDescriptor.cs" />
- <Compile Include="Reflection\SingleFieldAccessor.cs" />
- <Compile Include="ProtoPreconditions.cs" />
- <Compile Include="Reflection\TypeRegistry.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" />
- <Compile Include="WellKnownTypes\Empty.cs" />
- <Compile Include="WellKnownTypes\FieldMask.cs" />
- <Compile Include="WellKnownTypes\FieldMaskPartial.cs" />
- <Compile Include="WellKnownTypes\SourceContext.cs" />
- <Compile Include="WellKnownTypes\Struct.cs" />
- <Compile Include="WellKnownTypes\TimeExtensions.cs" />
- <Compile Include="WellKnownTypes\Timestamp.cs" />
- <Compile Include="WellKnownTypes\TimestampPartial.cs" />
- <Compile Include="WellKnownTypes\Type.cs" />
- <Compile Include="WellKnownTypes\ValuePartial.cs" />
- <Compile Include="WellKnownTypes\Wrappers.cs" />
- <Compile Include="WellKnownTypes\WrappersPartial.cs" />
- <Compile Include="WireFormat.cs" />
- </ItemGroup>
- <ItemGroup>
- <None Include="Google.Protobuf.nuspec" />
- <None Include="packages.config" />
- </ItemGroup>
- <ItemGroup />
- <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
- <Import Project="..\packages\NuSpec.ReferenceGenerator.1.4.1\build\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\NuSpec.ReferenceGenerator.targets" Condition="Exists('..\packages\NuSpec.ReferenceGenerator.1.4.1\build\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\NuSpec.ReferenceGenerator.targets')" />
- <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
- <PropertyGroup>
- <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
- </PropertyGroup>
- <Error Condition="!Exists('..\packages\NuSpec.ReferenceGenerator.1.4.1\build\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\NuSpec.ReferenceGenerator.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NuSpec.ReferenceGenerator.1.4.1\build\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\NuSpec.ReferenceGenerator.targets'))" />
- </Target>
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project> \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.nuspec b/csharp/src/Google.Protobuf/Google.Protobuf.nuspec
deleted file mode 100644
index 2aabf364..00000000
--- a/csharp/src/Google.Protobuf/Google.Protobuf.nuspec
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<package>
- <metadata>
- <id>Google.Protobuf</id>
- <title>Google Protocol Buffers C#</title>
- <summary>C# runtime library for Protocol Buffers - Google's data interchange format.</summary>
- <description>See project site for more info.</description>
- <version>3.0.0-beta3</version>
- <authors>Google Inc.</authors>
- <owners>protobuf-packages</owners>
- <licenseUrl>https://github.com/google/protobuf/blob/master/LICENSE</licenseUrl>
- <projectUrl>https://github.com/google/protobuf</projectUrl>
- <requireLicenseAcceptance>false</requireLicenseAcceptance>
- <releaseNotes>C# proto3 support</releaseNotes>
- <copyright>Copyright 2015, Google Inc.</copyright>
- <tags>Protocol Buffers Binary Serialization Format Google proto proto3</tags>
- <dependencies>
- <!-- Dependencies for older, monolithic-assembly platforms -->
- <group targetFramework="net45" />
- <group targetFramework="wp8" />
- <group targetFramework="win8" />
- <group targetFramework="wpa81" />
- <group targetFramework="xamarin.ios" />
- <group targetFramework="monotouch" />
- <group targetFramework="monoandroid" />
- <!-- Dependencies for newer, more granular platforms (.NET Core etc) -->
- <group targetFramework="dotnet">
- <dependency id="System.Collections" version="4.0.0" />
- <dependency id="System.Diagnostics.Debug" version="4.0.0" />
- <dependency id="System.Globalization" version="4.0.0" />
- <dependency id="System.IO" version="4.0.0" />
- <dependency id="System.Linq" version="4.0.0" />
- <dependency id="System.Linq.Expressions" version="4.0.0" />
- <dependency id="System.ObjectModel" version="4.0.0" />
- <dependency id="System.Reflection" version="4.0.0" />
- <dependency id="System.Reflection.Extensions" version="4.0.0" />
- <dependency id="System.Runtime" version="4.0.0" />
- <dependency id="System.Runtime.Extensions" version="4.0.0" />
- <dependency id="System.Text.Encoding" version="4.0.0" />
- <dependency id="System.Text.RegularExpressions" version="4.0.0" />
- <dependency id="System.Threading" version="4.0.0" />
- </group>
- </dependencies>
- </metadata>
- <files>
- <file src="bin/ReleaseSigned/Google.Protobuf.dll" target="lib/portable-net45+netcore45+wpa81+wp8" />
- <file src="bin/ReleaseSigned/Google.Protobuf.pdb" target="lib/portable-net45+netcore45+wpa81+wp8" />
- <file src="bin/ReleaseSigned/Google.Protobuf.xml" target="lib/portable-net45+netcore45+wpa81+wp8" />
- <file src="bin/ReleaseSigned/Google.Protobuf.dll" target="lib/dotnet" />
- <file src="bin/ReleaseSigned/Google.Protobuf.pdb" target="lib/dotnet" />
- <file src="bin/ReleaseSigned/Google.Protobuf.xml" target="lib/dotnet" />
- <file src="**\*.cs" target="src" />
- </files>
-</package> \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.xproj b/csharp/src/Google.Protobuf/Google.Protobuf.xproj
new file mode 100644
index 00000000..c68e0db3
--- /dev/null
+++ b/csharp/src/Google.Protobuf/Google.Protobuf.xproj
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
+ <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
+ </PropertyGroup>
+ <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>9b576380-726d-4142-8238-60a43ab0e35a</ProjectGuid>
+ <RootNamespace>Google.Protobuf</RootNamespace>
+ <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
+ <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <SchemaVersion>2.0</SchemaVersion>
+ </PropertyGroup>
+ <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
+</Project> \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs
index a894ffa1..d8a814d9 100644
--- a/csharp/src/Google.Protobuf/JsonFormatter.cs
+++ b/csharp/src/Google.Protobuf/JsonFormatter.cs
@@ -274,7 +274,6 @@ namespace Google.Protobuf
}
// Converted from src/google/protobuf/util/internal/utility.cc ToCamelCase
- // TODO: Use the new field in FieldDescriptor.
internal static string ToCamelCase(string input)
{
bool capitalizeNext = false;
@@ -305,6 +304,7 @@ namespace Google.Protobuf
(!wasCap || (i + 1 < input.Length && char.IsLower(input[i + 1]))))
{
firstWord = false;
+ result.Append(input[i]);
}
else
{
@@ -320,8 +320,16 @@ namespace Google.Protobuf
result.Append(char.ToUpperInvariant(input[i]));
continue;
}
+ else
+ {
+ result.Append(input[i]);
+ continue;
+ }
+ }
+ else
+ {
+ result.Append(char.ToLowerInvariant(input[i]));
}
- result.Append(input[i]);
}
return result.ToString();
}
diff --git a/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs b/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs
index 0516f18e..9b179bd7 100644
--- a/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs
+++ b/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs
@@ -30,7 +30,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
-using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
@@ -38,30 +37,13 @@ using System.Security;
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
-[assembly: AssemblyTitle("Google.Protobuf")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Google.Protobuf")]
-[assembly: AssemblyCopyright("Copyright © 2015")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
#if !NCRUNCH
[assembly: AllowPartiallyTrustedCallers]
#endif
-#if SIGNED
[assembly: InternalsVisibleTo("Google.Protobuf.Test, PublicKey=" +
"002400000480000094000000060200000024000052534131000400000100010025800fbcfc63a1" +
"7c66b303aae80b03a6beaa176bb6bef883be436f2a1579edd80ce23edf151a1f4ced97af83abcd" +
"981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" +
"b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" +
"c5ae9cb6")]
-#else
-[assembly: InternalsVisibleTo("Google.Protobuf.Test")]
-#endif
-
-[assembly: AssemblyVersion("3.0.0.0")]
-[assembly: AssemblyFileVersion("3.0.0.0")]
-[assembly: AssemblyInformationalVersion("3.0.0-beta3")]
diff --git a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
index 7ce75739..83e7928a 100644
--- a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
@@ -137,9 +137,9 @@ namespace Google.Protobuf.Reflection {
"dGVkQ29kZUluZm8SQQoKYW5ub3RhdGlvbhgBIAMoCzItLmdvb2dsZS5wcm90",
"b2J1Zi5HZW5lcmF0ZWRDb2RlSW5mby5Bbm5vdGF0aW9uGk8KCkFubm90YXRp",
"b24SEAoEcGF0aBgBIAMoBUICEAESEwoLc291cmNlX2ZpbGUYAiABKAkSDQoF",
- "YmVnaW4YAyABKAUSCwoDZW5kGAQgASgFQlgKE2NvbS5nb29nbGUucHJvdG9i",
- "dWZCEERlc2NyaXB0b3JQcm90b3NIAVoKZGVzY3JpcHRvcqICA0dQQqoCGkdv",
- "b2dsZS5Qcm90b2J1Zi5SZWZsZWN0aW9u"));
+ "YmVnaW4YAyABKAUSCwoDZW5kGAQgASgFQlsKE2NvbS5nb29nbGUucHJvdG9i",
+ "dWZCEERlc2NyaXB0b3JQcm90b3NIAVoKZGVzY3JpcHRvcqABAaICA0dQQqoC",
+ "Gkdvb2dsZS5Qcm90b2J1Zi5SZWZsZWN0aW9u"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
diff --git a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
index ab7cd922..94efea9e 100644
--- a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
@@ -251,17 +251,6 @@ namespace Google.Protobuf.Reflection
"Dependencies passed to FileDescriptor.BuildFrom() don't match " +
"those listed in the FileDescriptorProto.");
}
- for (int i = 0; i < proto.Dependency.Count; i++)
- {
- if (dependencies[i].Name != proto.Dependency[i])
- {
- throw new DescriptorValidationException(
- result,
- "Dependencies passed to FileDescriptor.BuildFrom() don't match " +
- "those listed in the FileDescriptorProto. Expected: " +
- proto.Dependency[i] + " but was: " + dependencies[i].Name);
- }
- }
result.CrossLink();
return result;
@@ -341,4 +330,4 @@ namespace Google.Protobuf.Reflection
/// </value>
public static FileDescriptor DescriptorProtoFileDescriptor { get { return DescriptorReflection.Descriptor; } }
}
-} \ No newline at end of file
+}
diff --git a/csharp/src/Google.Protobuf/packages.config b/csharp/src/Google.Protobuf/packages.config
deleted file mode 100644
index 40b8fd92..00000000
--- a/csharp/src/Google.Protobuf/packages.config
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
- <package id="NuSpec.ReferenceGenerator" version="1.4.1" targetFramework="portable45-net45+win8+wp8+wpa81" developmentDependency="true" />
-</packages> \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/project.json b/csharp/src/Google.Protobuf/project.json
new file mode 100644
index 00000000..9b831f12
--- /dev/null
+++ b/csharp/src/Google.Protobuf/project.json
@@ -0,0 +1,65 @@
+{
+ "version": "3.0.0",
+ "title": "Google Protocol Buffers",
+ "description": "See project site for more info.",
+ "authors": [ "Google Inc." ],
+ "copyright": "Copyright 2015, Google Inc.",
+
+ "packOptions": {
+ "summary": "C# runtime library for Protocol Buffers - Google's data interchange format.",
+ "tags": [ "Protocol", "Buffers", "Binary", "Serialization", "Format", "Google", "proto", "proto3" ],
+ "owners": [ "protobuf-packages" ],
+ "licenseUrl": "https://github.com/google/protobuf/blob/master/LICENSE",
+ "projectUrl": "https://github.com/google/protobuf",
+ "releaseNotes": "C# proto3 support",
+ "requireLicenseAcceptance": false,
+ "repository": {
+ "url": "https://github.com/nodatime/nodatime.git"
+ }
+ },
+
+ "buildOptions": {
+ "debugType": "portable",
+ "keyFile": "../../keys/Google.Protobuf.snk",
+ "xmlDoc": true
+ },
+
+ "configurations": {
+ "Debug": {
+ "buildOptions": {
+ "define": [ "DEBUG", "TRACE" ]
+ }
+ },
+ "Release": {
+ "buildOptions": {
+ "define": [ "RELEASE", "TRACE" ],
+ "optimize": true
+ }
+ }
+ },
+
+ "frameworks": {
+ // This target allows the package to be installed in a .NET 4.5+
+ // project without asking for myriad other dependencies.
+ "net45": {
+ },
+ "netstandard1.0": {
+ "dependencies": {
+ "System.Collections": "4.0.11",
+ "System.Diagnostics.Debug": "4.0.11",
+ "System.Globalization": "4.0.11",
+ "System.IO": "4.1.0",
+ "System.Linq": "4.1.0",
+ "System.Linq.Expressions": "4.1.0",
+ "System.ObjectModel": "4.0.12",
+ "System.Reflection": "4.1.0",
+ "System.Reflection.Extensions": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Runtime.Extensions": "4.1.0",
+ "System.Text.Encoding": "4.0.11",
+ "System.Text.RegularExpressions": "4.1.0",
+ "System.Threading": "4.0.11"
+ }
+ }
+ }
+}
diff --git a/docs/third_party.md b/docs/third_party.md
index 33666088..21a79079 100644
--- a/docs/third_party.md
+++ b/docs/third_party.md
@@ -36,6 +36,7 @@ These are projects we know about implementing Protocol Buffers for other program
* Erlang: http://piqi.org/
* Erlang: https://code.google.com/p/protoc-gen-erl/
* Erlang: https://github.com/basho/erlang_protobuffs
+* Erlang: https://github.com/tomas-abrahamsson/gpb
* Go: https://github.com/golang/protobuf (Google-official implementation)
* Go: http://code.google.com/p/goprotobuf/
* Go: https://github.com/akunspy/gopbuf
diff --git a/editors/protobuf-mode.el b/editors/protobuf-mode.el
index f615a0af..1cef4137 100644
--- a/editors/protobuf-mode.el
+++ b/editors/protobuf-mode.el
@@ -64,12 +64,13 @@
;;; Code:
(require 'cc-mode)
+(require 'cl)
(eval-when-compile
(require 'cc-langs)
(require 'cc-fonts))
-;; This mode does not inherit properties from other modes. So, we do not use
+;; This mode does not inherit properties from other modes. So, we do not use
;; the usual `c-add-language' function.
(eval-and-compile
(put 'protobuf-mode 'c-mode-prefix "protobuf-"))
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index c9d46885..2cd2acc0 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,63 +1,63 @@
-# Minimum CMake required
-cmake_minimum_required(VERSION 2.8.12)
-
-# Project
-project(protobuf-examples)
-
-# Find required protobuf package
-find_package(protobuf CONFIG REQUIRED)
-
-if(protobuf_VERBOSE)
- message(STATUS "Using Protocol Buffers ${Protobuf_VERSION}")
-endif()
-
-set(CMAKE_INCLUDE_CURRENT_DIR TRUE)
-
-# http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F
-if(MSVC AND protobuf_MSVC_STATIC_RUNTIME)
- foreach(flag_var
- CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
- CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
- if(${flag_var} MATCHES "/MD")
- string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
- endif(${flag_var} MATCHES "/MD")
- endforeach()
-endif()
-
-foreach(example add_person list_people)
- set(${example}_SRCS ${example}.cc)
- set(${example}_PROTOS addressbook.proto)
-
- #Code Generation
- if(protobuf_MODULE_COMPATIBLE) #Legacy Support
- protobuf_generate_cpp(${example}_PROTO_SRCS ${example}_PROTO_HDRS ${${example}_PROTOS})
- list(APPEND ${example}_SRCS ${${example}_PROTO_SRCS} ${${example}_PROTO_HDRS})
- else()
-
- foreach(proto_file ${${example}_PROTOS})
- get_filename_component(proto_file_abs ${proto_file} ABSOLUTE)
- get_filename_component(basename ${proto_file} NAME_WE)
- set(generated_files ${basename}.pb.cc ${basename}.pb.h)
- list(APPEND ${example}_SRCS ${generated_files})
-
- add_custom_command(
- OUTPUT ${generated_files}
- COMMAND protobuf::protoc
- ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} -I ${CMAKE_CURRENT_SOURCE_DIR} ${proto_file_abs}
- COMMENT "Generating ${generated_files} from ${proto_file}"
- VERBATIM
- )
- endforeach()
- endif()
-
- #Executable setup
- set(executable_name ${example}_cpp)
- add_executable(${executable_name} ${${example}_SRCS} ${${example}_PROTOS})
- if(protobuf_MODULE_COMPATIBLE) #Legacy mode
- target_include_directories(${executable_name} PUBLIC ${PROTOBUF_INCLUDE_DIRS})
- target_link_libraries(${executable_name} ${PROTOBUF_LIBRARIES})
- else()
- target_link_libraries(${executable_name} protobuf::libprotobuf)
- endif()
-
-endforeach()
+# Minimum CMake required
+cmake_minimum_required(VERSION 2.8.12)
+
+# Project
+project(protobuf-examples)
+
+# Find required protobuf package
+find_package(protobuf CONFIG REQUIRED)
+
+if(protobuf_VERBOSE)
+ message(STATUS "Using Protocol Buffers ${Protobuf_VERSION}")
+endif()
+
+set(CMAKE_INCLUDE_CURRENT_DIR TRUE)
+
+# http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F
+if(MSVC AND protobuf_MSVC_STATIC_RUNTIME)
+ foreach(flag_var
+ CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+ CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+ if(${flag_var} MATCHES "/MD")
+ string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+ endif(${flag_var} MATCHES "/MD")
+ endforeach()
+endif()
+
+foreach(example add_person list_people)
+ set(${example}_SRCS ${example}.cc)
+ set(${example}_PROTOS addressbook.proto)
+
+ #Code Generation
+ if(protobuf_MODULE_COMPATIBLE) #Legacy Support
+ protobuf_generate_cpp(${example}_PROTO_SRCS ${example}_PROTO_HDRS ${${example}_PROTOS})
+ list(APPEND ${example}_SRCS ${${example}_PROTO_SRCS} ${${example}_PROTO_HDRS})
+ else()
+
+ foreach(proto_file ${${example}_PROTOS})
+ get_filename_component(proto_file_abs ${proto_file} ABSOLUTE)
+ get_filename_component(basename ${proto_file} NAME_WE)
+ set(generated_files ${basename}.pb.cc ${basename}.pb.h)
+ list(APPEND ${example}_SRCS ${generated_files})
+
+ add_custom_command(
+ OUTPUT ${generated_files}
+ COMMAND protobuf::protoc
+ ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} -I ${CMAKE_CURRENT_SOURCE_DIR} ${proto_file_abs}
+ COMMENT "Generating ${generated_files} from ${proto_file}"
+ VERBATIM
+ )
+ endforeach()
+ endif()
+
+ #Executable setup
+ set(executable_name ${example}_cpp)
+ add_executable(${executable_name} ${${example}_SRCS} ${${example}_PROTOS})
+ if(protobuf_MODULE_COMPATIBLE) #Legacy mode
+ target_include_directories(${executable_name} PUBLIC ${PROTOBUF_INCLUDE_DIRS})
+ target_link_libraries(${executable_name} ${PROTOBUF_LIBRARIES})
+ else()
+ target_link_libraries(${executable_name} protobuf::libprotobuf)
+ endif()
+
+endforeach()
diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh
index c170c837..668e6d13 100755
--- a/generate_descriptor_proto.sh
+++ b/generate_descriptor_proto.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
# Run this script to regenerate descriptor.pb.{h,cc} after the protocol
# compiler changes. Since these files are compiled into the protocol compiler
diff --git a/gmock.BUILD b/gmock.BUILD
index 82abf275..b1ae15a9 100644
--- a/gmock.BUILD
+++ b/gmock.BUILD
@@ -1,19 +1,19 @@
cc_library(
name = "gtest",
srcs = [
- "gmock-1.7.0/gtest/src/gtest-all.cc",
- "gmock-1.7.0/src/gmock-all.cc",
+ "googletest/src/gtest-all.cc",
+ "googlemock/src/gmock-all.cc",
],
hdrs = glob([
- "gmock-1.7.0/**/*.h",
- "gmock-1.7.0/gtest/src/*.cc",
- "gmock-1.7.0/src/*.cc",
+ "**/*.h",
+ "googletest/src/*.cc",
+ "googlemock/src/*.cc",
]),
includes = [
- "gmock-1.7.0",
- "gmock-1.7.0/gtest",
- "gmock-1.7.0/gtest/include",
- "gmock-1.7.0/include",
+ "googlemock",
+ "googletest",
+ "googletest/include",
+ "googlemock/include",
],
linkopts = ["-pthread"],
visibility = ["//visibility:public"],
@@ -21,7 +21,7 @@ cc_library(
cc_library(
name = "gtest_main",
- srcs = ["gmock-1.7.0/src/gmock_main.cc"],
+ srcs = ["googlemock/src/gmock_main.cc"],
linkopts = ["-pthread"],
visibility = ["//visibility:public"],
deps = [":gtest"],
diff --git a/java/compatibility_tests/v2.5.0/test.sh b/java/compatibility_tests/v2.5.0/test.sh
index b7922b1a..5d5e9ed4 100755
--- a/java/compatibility_tests/v2.5.0/test.sh
+++ b/java/compatibility_tests/v2.5.0/test.sh
@@ -21,15 +21,23 @@ case "$1" in
;;
2.6.1)
OLD_VERSION=2.6.1
- OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/2.6.1-build2/protoc-2.6.1-build2-linux-x86_32.exe
+ OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/2.6.1-build2/protoc-2.6.1-build2-linux-x86_64.exe
;;
3.0.0-beta-1)
OLD_VERSION=3.0.0-beta-1
- OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-1/protoc-3.0.0-beta-1-linux-x86_32.exe
+ OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-1/protoc-3.0.0-beta-1-linux-x86_64.exe
;;
3.0.0-beta-2)
OLD_VERSION=3.0.0-beta-2
- OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-2/protoc-3.0.0-beta-2-linux-x86_32.exe
+ OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-2/protoc-3.0.0-beta-2-linux-x86_64.exe
+ ;;
+ 3.0.0-beta-3)
+ OLD_VERSION=3.0.0-beta-3
+ OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-3/protoc-3.0.0-beta-3-linux-x86_64.exe
+ ;;
+ 3.0.0-beta-4)
+ OLD_VERSION=3.0.0-beta-4
+ OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-4/protoc-3.0.0-beta-4-linux-x86_64.exe
;;
*)
echo "[ERROR]: Unknown version number: $1"
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RepeatedFieldBuilderTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RepeatedFieldBuilderTest.java
deleted file mode 100644
index 9a1d8cad..00000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RepeatedFieldBuilderTest.java
+++ /dev/null
@@ -1,191 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
-
-import junit.framework.TestCase;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Tests for {@link RepeatedFieldBuilder}. This tests basic functionality.
- * More extensive testing is provided via other tests that exercise the
- * builder.
- *
- * @author jonp@google.com (Jon Perlow)
- */
-public class RepeatedFieldBuilderTest extends TestCase {
-
- public void testBasicUse() {
- TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
- RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
- builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
- builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
- assertEquals(0, builder.getMessage(0).getOptionalInt32());
- assertEquals(1, builder.getMessage(1).getOptionalInt32());
-
- List<TestAllTypes> list = builder.build();
- assertEquals(2, list.size());
- assertEquals(0, list.get(0).getOptionalInt32());
- assertEquals(1, list.get(1).getOptionalInt32());
- assertIsUnmodifiable(list);
-
- // Make sure it doesn't change.
- List<TestAllTypes> list2 = builder.build();
- assertSame(list, list2);
- assertEquals(0, mockParent.getInvalidationCount());
- }
-
- public void testGoingBackAndForth() {
- TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
- RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
- builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
- builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
- assertEquals(0, builder.getMessage(0).getOptionalInt32());
- assertEquals(1, builder.getMessage(1).getOptionalInt32());
-
- // Convert to list
- List<TestAllTypes> list = builder.build();
- assertEquals(2, list.size());
- assertEquals(0, list.get(0).getOptionalInt32());
- assertEquals(1, list.get(1).getOptionalInt32());
- assertIsUnmodifiable(list);
-
- // Update 0th item
- assertEquals(0, mockParent.getInvalidationCount());
- builder.getBuilder(0).setOptionalString("foo");
- assertEquals(1, mockParent.getInvalidationCount());
- list = builder.build();
- assertEquals(2, list.size());
- assertEquals(0, list.get(0).getOptionalInt32());
- assertEquals("foo", list.get(0).getOptionalString());
- assertEquals(1, list.get(1).getOptionalInt32());
- assertIsUnmodifiable(list);
- assertEquals(1, mockParent.getInvalidationCount());
- }
-
- public void testVariousMethods() {
- TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
- RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
- builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
- builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(2).build());
- builder.addBuilder(0, TestAllTypes.getDefaultInstance())
- .setOptionalInt32(0);
- builder.addBuilder(TestAllTypes.getDefaultInstance()).setOptionalInt32(3);
-
- assertEquals(0, builder.getMessage(0).getOptionalInt32());
- assertEquals(1, builder.getMessage(1).getOptionalInt32());
- assertEquals(2, builder.getMessage(2).getOptionalInt32());
- assertEquals(3, builder.getMessage(3).getOptionalInt32());
-
- assertEquals(0, mockParent.getInvalidationCount());
- List<TestAllTypes> messages = builder.build();
- assertEquals(4, messages.size());
- assertSame(messages, builder.build()); // expect same list
-
- // Remove a message.
- builder.remove(2);
- assertEquals(1, mockParent.getInvalidationCount());
- assertEquals(3, builder.getCount());
- assertEquals(0, builder.getMessage(0).getOptionalInt32());
- assertEquals(1, builder.getMessage(1).getOptionalInt32());
- assertEquals(3, builder.getMessage(2).getOptionalInt32());
-
- // Remove a builder.
- builder.remove(0);
- assertEquals(1, mockParent.getInvalidationCount());
- assertEquals(2, builder.getCount());
- assertEquals(1, builder.getMessage(0).getOptionalInt32());
- assertEquals(3, builder.getMessage(1).getOptionalInt32());
-
- // Test clear.
- builder.clear();
- assertEquals(1, mockParent.getInvalidationCount());
- assertEquals(0, builder.getCount());
- assertTrue(builder.isEmpty());
- }
-
- public void testLists() {
- TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
- RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
- builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
- builder.addMessage(0,
- TestAllTypes.newBuilder().setOptionalInt32(0).build());
- assertEquals(0, builder.getMessage(0).getOptionalInt32());
- assertEquals(1, builder.getMessage(1).getOptionalInt32());
-
- // Use list of builders.
- List<TestAllTypes.Builder> builders = builder.getBuilderList();
- assertEquals(0, builders.get(0).getOptionalInt32());
- assertEquals(1, builders.get(1).getOptionalInt32());
- builders.get(0).setOptionalInt32(10);
- builders.get(1).setOptionalInt32(11);
-
- // Use list of protos
- List<TestAllTypes> protos = builder.getMessageList();
- assertEquals(10, protos.get(0).getOptionalInt32());
- assertEquals(11, protos.get(1).getOptionalInt32());
-
- // Add an item to the builders and verify it's updated in both
- builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(12).build());
- assertEquals(3, builders.size());
- assertEquals(3, protos.size());
- }
-
- private void assertIsUnmodifiable(List<?> list) {
- if (list == Collections.emptyList()) {
- // OKAY -- Need to check this b/c EmptyList allows you to call clear.
- } else {
- try {
- list.clear();
- fail("List wasn't immutable");
- } catch (UnsupportedOperationException e) {
- // good
- }
- }
- }
-
- private RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder>
- newRepeatedFieldBuilder(TestUtil.MockBuilderParent parent) {
- return new RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder>(Collections.<TestAllTypes>emptyList(), false,
- parent, false);
- }
-}
diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/SingleFieldBuilderTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/SingleFieldBuilderTest.java
deleted file mode 100644
index 534fee6d..00000000
--- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/SingleFieldBuilderTest.java
+++ /dev/null
@@ -1,156 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf.test;
-import com.google.protobuf.*;
-
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
-
-import junit.framework.TestCase;
-
-/**
- * Tests for {@link SingleFieldBuilder}. This tests basic functionality.
- * More extensive testing is provided via other tests that exercise the
- * builder.
- *
- * @author jonp@google.com (Jon Perlow)
- */
-public class SingleFieldBuilderTest extends TestCase {
-
- public void testBasicUseAndInvalidations() {
- TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
- SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder> builder =
- new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder>(
- TestAllTypes.getDefaultInstance(),
- mockParent,
- false);
- assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
- assertEquals(TestAllTypes.getDefaultInstance(),
- builder.getBuilder().buildPartial());
- assertEquals(0, mockParent.getInvalidationCount());
-
- builder.getBuilder().setOptionalInt32(10);
- assertEquals(0, mockParent.getInvalidationCount());
- TestAllTypes message = builder.build();
- assertEquals(10, message.getOptionalInt32());
-
- // Test that we receive invalidations now that build has been called.
- assertEquals(0, mockParent.getInvalidationCount());
- builder.getBuilder().setOptionalInt32(20);
- assertEquals(1, mockParent.getInvalidationCount());
-
- // Test that we don't keep getting invalidations on every change
- builder.getBuilder().setOptionalInt32(30);
- assertEquals(1, mockParent.getInvalidationCount());
-
- }
-
- public void testSetMessage() {
- TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
- SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder> builder =
- new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder>(
- TestAllTypes.getDefaultInstance(),
- mockParent,
- false);
- builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
- assertEquals(0, builder.getMessage().getOptionalInt32());
-
- // Update message using the builder
- builder.getBuilder().setOptionalInt32(1);
- assertEquals(0, mockParent.getInvalidationCount());
- assertEquals(1, builder.getBuilder().getOptionalInt32());
- assertEquals(1, builder.getMessage().getOptionalInt32());
- builder.build();
- builder.getBuilder().setOptionalInt32(2);
- assertEquals(2, builder.getBuilder().getOptionalInt32());
- assertEquals(2, builder.getMessage().getOptionalInt32());
-
- // Make sure message stays cached
- assertSame(builder.getMessage(), builder.getMessage());
- }
-
- public void testClear() {
- TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
- SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder> builder =
- new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder>(
- TestAllTypes.getDefaultInstance(),
- mockParent,
- false);
- builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
- assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
- builder.clear();
- assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
-
- builder.getBuilder().setOptionalInt32(1);
- assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
- builder.clear();
- assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
- }
-
- public void testMerge() {
- TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
- SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder> builder =
- new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder>(
- TestAllTypes.getDefaultInstance(),
- mockParent,
- false);
-
- // Merge into default field.
- builder.mergeFrom(TestAllTypes.getDefaultInstance());
- assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
-
- // Merge into non-default field on existing builder.
- builder.getBuilder().setOptionalInt32(2);
- builder.mergeFrom(TestAllTypes.newBuilder()
- .setOptionalDouble(4.0)
- .buildPartial());
- assertEquals(2, builder.getMessage().getOptionalInt32());
- assertEquals(4.0, builder.getMessage().getOptionalDouble());
-
- // Merge into non-default field on existing message
- builder.setMessage(TestAllTypes.newBuilder()
- .setOptionalInt32(10)
- .buildPartial());
- builder.mergeFrom(TestAllTypes.newBuilder()
- .setOptionalDouble(5.0)
- .buildPartial());
- assertEquals(10, builder.getMessage().getOptionalInt32());
- assertEquals(5.0, builder.getMessage().getOptionalDouble());
- }
-}
diff --git a/java/core/pom.xml b/java/core/pom.xml
index 0d4c5c75..39d67818 100644
--- a/java/core/pom.xml
+++ b/java/core/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
- <version>3.0.0-beta-3</version>
+ <version>3.0.0</version>
</parent>
<artifactId>protobuf-java</artifactId>
diff --git a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
index 46ddbf48..7639efcf 100644
--- a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -490,7 +490,7 @@ public abstract class AbstractMessage
/**
* Used to support nested builders and called to mark this builder as clean.
- * Clean builders will propagate the {@link BuildParent#markDirty()} event
+ * Clean builders will propagate the {@link BuilderParent#markDirty()} event
* to their parent builders, while dirty builders will not, as their parents
* should be dirty already.
*
diff --git a/java/core/src/main/java/com/google/protobuf/ByteOutput.java b/java/core/src/main/java/com/google/protobuf/ByteOutput.java
index 8b7b04c8..ee588753 100644
--- a/java/core/src/main/java/com/google/protobuf/ByteOutput.java
+++ b/java/core/src/main/java/com/google/protobuf/ByteOutput.java
@@ -37,11 +37,11 @@ import java.nio.ByteBuffer;
* An output target for raw bytes. This interface provides semantics that support two types of
* writing:
*
- * <p/><b>Traditional write operations:</b>
+ * <p><b>Traditional write operations:</b>
* (as defined by {@link java.io.OutputStream}) where the target method is responsible for either
* copying the data or completing the write before returning from the method call.
*
- * <p/><b>Lazy write operations:</b> where the caller guarantees that it will never modify the
+ * <p><b>Lazy write operations:</b> where the caller guarantees that it will never modify the
* provided buffer and it can therefore be considered immutable. The target method is free to
* maintain a reference to the buffer beyond the scope of the method call (e.g. until the write
* operation completes).
diff --git a/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java b/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
index 576a350f..e5515285 100644
--- a/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
+++ b/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
@@ -145,6 +145,44 @@ public abstract class CodedOutputStream extends ByteOutput {
}
/**
+ * Configures serialization to be deterministic.
+ *
+ * <p>The deterministic serialization guarantees that for a given binary, equal (defined by the
+ * {@code equals()} methods in protos) messages will always be serialized to the same bytes. This
+ * implies:
+ *
+ * <ul>
+ * <li>repeated serialization of a message will return the same bytes
+ * <li>different processes of the same binary (which may be executing on different machines) will
+ * serialize equal messages to the same bytes.
+ * </ul>
+ *
+ * <p>Note the deterministic serialization is NOT canonical across languages; it is also unstable
+ * across different builds with schema changes due to unknown fields. Users who need canonical
+ * serialization, e.g. persistent storage in a canonical form, fingerprinting, etc, should define
+ * their own canonicalization specification and implement the serializer using reflection APIs
+ * rather than relying on this API.
+ *
+ * <p> Once set, the serializer will: (Note this is an implementation detail and may subject to
+ * change in the future)
+ *
+ * <ul>
+ * <li> sort map entries by keys in lexicographical order or numerical order. Note: For string
+ * keys, the order is based on comparing the Unicode value of each character in the strings.
+ * The order may be different from the deterministic serialization in other languages where
+ * maps are sorted on the lexicographical order of the UTF8 encoded keys.
+ * </ul>
+ */
+ void useDeterministicSerialization() {
+ serializationDeterministic = true;
+ }
+
+ boolean isSerializationDeterministic() {
+ return serializationDeterministic;
+ }
+ private boolean serializationDeterministic;
+
+ /**
* Create a new {@code CodedOutputStream} that writes to the given {@link ByteBuffer}.
*
* @deprecated the size parameter is no longer used since use of an internal buffer is useless
diff --git a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
index 859a9e8f..c54da67f 100644
--- a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
+++ b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -526,6 +526,14 @@ public final class DynamicMessage extends AbstractMessage {
fields.clearField(oldField);
}
oneofCases[index] = field;
+ } else if (field.getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3) {
+ if (!field.isRepeated()
+ && field.getJavaType() != FieldDescriptor.JavaType.MESSAGE
+ && value.equals(field.getDefaultValue())) {
+ // In proto3, setting a field to its default value is equivalent to clearing the field.
+ fields.clearField(field);
+ return this;
+ }
}
fields.setField(field, value);
return this;
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
index 2c87302b..cea05794 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -1396,7 +1396,7 @@ public abstract class GeneratedMessage extends AbstractMessage
return setExtension((ExtensionLite<MessageType, Type>) extension, value);
}
/** Set the value of an extension. */
- public final <Type> BuilderType setExtension(
+ public <Type> BuilderType setExtension(
final GeneratedExtension<MessageType, Type> extension, final Type value) {
return setExtension((ExtensionLite<MessageType, Type>) extension, value);
}
@@ -1407,7 +1407,7 @@ public abstract class GeneratedMessage extends AbstractMessage
return setExtension((ExtensionLite<MessageType, List<Type>>) extension, index, value);
}
/** Set the value of one element of a repeated extension. */
- public final <Type> BuilderType setExtension(
+ public <Type> BuilderType setExtension(
final GeneratedExtension<MessageType, List<Type>> extension,
final int index, final Type value) {
return setExtension((ExtensionLite<MessageType, List<Type>>) extension, index, value);
@@ -1418,7 +1418,7 @@ public abstract class GeneratedMessage extends AbstractMessage
return addExtension((ExtensionLite<MessageType, List<Type>>) extension, value);
}
/** Append a value to a repeated extension. */
- public final <Type> BuilderType addExtension(
+ public <Type> BuilderType addExtension(
final GeneratedExtension<MessageType, List<Type>> extension, final Type value) {
return addExtension((ExtensionLite<MessageType, List<Type>>) extension, value);
}
@@ -1428,7 +1428,7 @@ public abstract class GeneratedMessage extends AbstractMessage
return clearExtension((ExtensionLite<MessageType, ?>) extension);
}
/** Clear an extension. */
- public final <Type> BuilderType clearExtension(
+ public <Type> BuilderType clearExtension(
final GeneratedExtension<MessageType, ?> extension) {
return clearExtension((ExtensionLite<MessageType, ?>) extension);
}
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
new file mode 100644
index 00000000..5dfe7ff7
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
@@ -0,0 +1,2716 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+import com.google.protobuf.GeneratedMessage.GeneratedExtension;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * All generated protocol message classes extend this class. This class
+ * implements most of the Message and Builder interfaces using Java reflection.
+ * Users can ignore this class and pretend that generated messages implement
+ * the Message interface directly.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class GeneratedMessageV3 extends AbstractMessage
+ implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * For testing. Allows a test to disable the optimization that avoids using
+ * field builders for nested messages until they are requested. By disabling
+ * this optimization, existing tests can be reused to test the field builders.
+ */
+ protected static boolean alwaysUseFieldBuilders = false;
+
+ /** For use by generated code only. */
+ protected UnknownFieldSet unknownFields;
+
+ protected GeneratedMessageV3() {
+ unknownFields = UnknownFieldSet.getDefaultInstance();
+ }
+
+ protected GeneratedMessageV3(Builder<?> builder) {
+ unknownFields = builder.getUnknownFields();
+ }
+
+ @Override
+ public Parser<? extends GeneratedMessageV3> getParserForType() {
+ throw new UnsupportedOperationException(
+ "This is supposed to be overridden by subclasses.");
+ }
+
+ /**
+ * For testing. Allows a test to disable the optimization that avoids using
+ * field builders for nested messages until they are requested. By disabling
+ * this optimization, existing tests can be reused to test the field builders.
+ * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}.
+ */
+ static void enableAlwaysUseFieldBuildersForTesting() {
+ alwaysUseFieldBuilders = true;
+ }
+
+ /**
+ * Get the FieldAccessorTable for this type. We can't have the message
+ * class pass this in to the constructor because of bootstrapping trouble
+ * with DescriptorProtos.
+ */
+ protected abstract FieldAccessorTable internalGetFieldAccessorTable();
+
+ @Override
+ public Descriptor getDescriptorForType() {
+ return internalGetFieldAccessorTable().descriptor;
+ }
+
+ /**
+ * Internal helper to return a modifiable map containing all the fields.
+ * The returned Map is modifialbe so that the caller can add additional
+ * extension fields to implement {@link #getAllFields()}.
+ *
+ * @param getBytesForString whether to generate ByteString for string fields
+ */
+ private Map<FieldDescriptor, Object> getAllFieldsMutable(
+ boolean getBytesForString) {
+ final TreeMap<FieldDescriptor, Object> result =
+ new TreeMap<FieldDescriptor, Object>();
+ final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
+ 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 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;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ for (final FieldDescriptor field : getDescriptorForType().getFields()) {
+ // Check that all required fields are present.
+ if (field.isRequired()) {
+ if (!hasField(field)) {
+ return false;
+ }
+ }
+ // Check that embedded messages are initialized.
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ if (field.isRepeated()) {
+ @SuppressWarnings("unchecked") final
+ List<Message> messageList = (List<Message>) getField(field);
+ for (final Message element : messageList) {
+ if (!element.isInitialized()) {
+ return false;
+ }
+ }
+ } else {
+ if (hasField(field) && !((Message) getField(field)).isInitialized()) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ return Collections.unmodifiableMap(
+ getAllFieldsMutable(/* getBytesForString = */ false));
+ }
+
+ /**
+ * Returns a collection of all the fields in this message which are set
+ * and their corresponding values. A singular ("required" or "optional")
+ * field is set iff hasField() returns true for that field. A "repeated"
+ * field is set iff getRepeatedFieldCount() is greater than zero. The
+ * values are exactly what would be returned by calling
+ * {@link #getFieldRaw(Descriptors.FieldDescriptor)} for each field. The map
+ * is guaranteed to be a sorted map, so iterating over it will return fields
+ * in order by field number.
+ */
+ Map<FieldDescriptor, Object> getAllFieldsRaw() {
+ return Collections.unmodifiableMap(
+ getAllFieldsMutable(/* getBytesForString = */ true));
+ }
+
+ @Override
+ public boolean hasOneof(final OneofDescriptor oneof) {
+ return internalGetFieldAccessorTable().getOneof(oneof).has(this);
+ }
+
+ @Override
+ public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) {
+ return internalGetFieldAccessorTable().getOneof(oneof).get(this);
+ }
+
+ @Override
+ public boolean hasField(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).has(this);
+ }
+
+ @Override
+ public Object getField(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).get(this);
+ }
+
+ /**
+ * Obtains the value of the given field, or the default value if it is
+ * not set. For primitive fields, the boxed primitive value is returned.
+ * For enum fields, the EnumValueDescriptor for the value is returned. For
+ * embedded message fields, the sub-message is returned. For repeated
+ * fields, a java.util.List is returned. For present string fields, a
+ * ByteString is returned representing the bytes that the field contains.
+ */
+ Object getFieldRaw(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).getRaw(this);
+ }
+
+ @Override
+ public int getRepeatedFieldCount(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field)
+ .getRepeatedCount(this);
+ }
+
+ @Override
+ public Object getRepeatedField(final FieldDescriptor field, final int index) {
+ return internalGetFieldAccessorTable().getField(field)
+ .getRepeated(this, index);
+ }
+
+ @Override
+ public UnknownFieldSet getUnknownFields() {
+ throw new UnsupportedOperationException(
+ "This is supposed to be overridden by subclasses.");
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ protected boolean parseUnknownField(
+ CodedInputStream input,
+ UnknownFieldSet.Builder unknownFields,
+ ExtensionRegistryLite extensionRegistry,
+ int tag) throws IOException {
+ return unknownFields.mergeFieldFrom(tag, input);
+ }
+
+ protected static <M extends Message> M parseWithIOException(Parser<M> parser, InputStream input)
+ throws IOException {
+ try {
+ return parser.parseFrom(input);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
+ protected static <M extends Message> M parseWithIOException(Parser<M> parser, InputStream input,
+ ExtensionRegistryLite extensions) throws IOException {
+ try {
+ return parser.parseFrom(input, extensions);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
+ protected static <M extends Message> M parseWithIOException(Parser<M> parser,
+ CodedInputStream input) throws IOException {
+ try {
+ return parser.parseFrom(input);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
+ protected static <M extends Message> M parseWithIOException(Parser<M> parser,
+ CodedInputStream input, ExtensionRegistryLite extensions) throws IOException {
+ try {
+ return parser.parseFrom(input, extensions);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
+ protected static <M extends Message> M parseDelimitedWithIOException(Parser<M> parser,
+ InputStream input) throws IOException {
+ try {
+ return parser.parseDelimitedFrom(input);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
+ protected static <M extends Message> M parseDelimitedWithIOException(Parser<M> parser,
+ InputStream input, ExtensionRegistryLite extensions) throws IOException {
+ try {
+ return parser.parseDelimitedFrom(input, extensions);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
+ @Override
+ public void writeTo(final CodedOutputStream output) throws IOException {
+ MessageReflection.writeMessageTo(this, getAllFieldsRaw(), output, false);
+ }
+
+ @Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) {
+ return size;
+ }
+
+ memoizedSize = MessageReflection.getSerializedSize(
+ this, getAllFieldsRaw());
+ return memoizedSize;
+ }
+
+
+
+ /**
+ * Used by parsing constructors in generated classes.
+ */
+ protected void makeExtensionsImmutable() {
+ // Noop for messages without extensions.
+ }
+
+ /**
+ * TODO(xiaofeng): remove this after b/29368482 is fixed. We need to move this
+ * interface to AbstractMessage in order to versioning GeneratedMessageV3 but
+ * this move breaks binary compatibility for AppEngine. After AppEngine is
+ * fixed we can exlude this from google3.
+ */
+ protected interface BuilderParent extends AbstractMessage.BuilderParent {}
+
+ /**
+ * TODO(xiaofeng): remove this together with GeneratedMessageV3.BuilderParent.
+ */
+ protected abstract Message.Builder newBuilderForType(BuilderParent parent);
+
+ @Override
+ protected Message.Builder newBuilderForType(final AbstractMessage.BuilderParent parent) {
+ return newBuilderForType(new BuilderParent() {
+ @Override
+ public void markDirty() {
+ parent.markDirty();
+ }
+ });
+ }
+
+
+ @SuppressWarnings("unchecked")
+ public abstract static class Builder <BuilderType extends Builder<BuilderType>>
+ extends AbstractMessage.Builder<BuilderType> {
+
+ private BuilderParent builderParent;
+
+ private BuilderParentImpl meAsParent;
+
+ // Indicates that we've built a message and so we are now obligated
+ // to dispatch dirty invalidations. See GeneratedMessageV3.BuilderListener.
+ private boolean isClean;
+
+ private UnknownFieldSet unknownFields =
+ UnknownFieldSet.getDefaultInstance();
+
+ protected Builder() {
+ this(null);
+ }
+
+ protected Builder(BuilderParent builderParent) {
+ this.builderParent = builderParent;
+ }
+
+ @Override
+ void dispose() {
+ builderParent = null;
+ }
+
+ /**
+ * Called by the subclass when a message is built.
+ */
+ protected void onBuilt() {
+ if (builderParent != null) {
+ markClean();
+ }
+ }
+
+ /**
+ * Called by the subclass or a builder to notify us that a message was
+ * built and may be cached and therefore invalidations are needed.
+ */
+ @Override
+ protected void markClean() {
+ this.isClean = true;
+ }
+
+ /**
+ * Gets whether invalidations are needed
+ *
+ * @return whether invalidations are needed
+ */
+ protected boolean isClean() {
+ return isClean;
+ }
+
+ @Override
+ public BuilderType clone() {
+ BuilderType builder =
+ (BuilderType) getDefaultInstanceForType().newBuilderForType();
+ builder.mergeFrom(buildPartial());
+ return builder;
+ }
+
+ /**
+ * Called by the initialization and clear code paths to allow subclasses to
+ * reset any of their builtin fields back to the initial values.
+ */
+ @Override
+ public BuilderType clear() {
+ unknownFields = UnknownFieldSet.getDefaultInstance();
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ /**
+ * Get the FieldAccessorTable for this type. We can't have the message
+ * class pass this in to the constructor because of bootstrapping trouble
+ * with DescriptorProtos.
+ */
+ protected abstract FieldAccessorTable internalGetFieldAccessorTable();
+
+ @Override
+ public Descriptor getDescriptorForType() {
+ return internalGetFieldAccessorTable().descriptor;
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ return Collections.unmodifiableMap(getAllFieldsMutable());
+ }
+
+ /** Internal helper which returns a mutable map. */
+ private Map<FieldDescriptor, Object> getAllFieldsMutable() {
+ final TreeMap<FieldDescriptor, Object> result =
+ new TreeMap<FieldDescriptor, Object>();
+ final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
+ 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 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;
+ }
+
+ @Override
+ public Message.Builder newBuilderForField(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).newBuilder();
+ }
+
+ @Override
+ public Message.Builder getFieldBuilder(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).getBuilder(this);
+ }
+
+ @Override
+ public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) {
+ return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder(
+ this, index);
+ }
+
+ @Override
+ public boolean hasOneof(final OneofDescriptor oneof) {
+ return internalGetFieldAccessorTable().getOneof(oneof).has(this);
+ }
+
+ @Override
+ public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) {
+ return internalGetFieldAccessorTable().getOneof(oneof).get(this);
+ }
+
+ @Override
+ public boolean hasField(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).has(this);
+ }
+
+ @Override
+ public Object getField(final FieldDescriptor field) {
+ Object object = internalGetFieldAccessorTable().getField(field).get(this);
+ if (field.isRepeated()) {
+ // The underlying list object is still modifiable at this point.
+ // Make sure not to expose the modifiable list to the caller.
+ return Collections.unmodifiableList((List) object);
+ } else {
+ return object;
+ }
+ }
+
+ @Override
+ public BuilderType setField(final FieldDescriptor field, final Object value) {
+ internalGetFieldAccessorTable().getField(field).set(this, value);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType clearField(final FieldDescriptor field) {
+ internalGetFieldAccessorTable().getField(field).clear(this);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType clearOneof(final OneofDescriptor oneof) {
+ internalGetFieldAccessorTable().getOneof(oneof).clear(this);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public int getRepeatedFieldCount(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field)
+ .getRepeatedCount(this);
+ }
+
+ @Override
+ public Object getRepeatedField(final FieldDescriptor field, final int index) {
+ return internalGetFieldAccessorTable().getField(field)
+ .getRepeated(this, index);
+ }
+
+ @Override
+ public BuilderType setRepeatedField(
+ final FieldDescriptor field, final int index, final Object value) {
+ internalGetFieldAccessorTable().getField(field)
+ .setRepeated(this, index, value);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType addRepeatedField(final FieldDescriptor field, final Object value) {
+ internalGetFieldAccessorTable().getField(field).addRepeated(this, value);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType setUnknownFields(final UnknownFieldSet unknownFields) {
+ this.unknownFields = unknownFields;
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType mergeUnknownFields(
+ final UnknownFieldSet unknownFields) {
+ this.unknownFields =
+ UnknownFieldSet.newBuilder(this.unknownFields)
+ .mergeFrom(unknownFields)
+ .build();
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ for (final FieldDescriptor field : getDescriptorForType().getFields()) {
+ // Check that all required fields are present.
+ if (field.isRequired()) {
+ if (!hasField(field)) {
+ return false;
+ }
+ }
+ // Check that embedded messages are initialized.
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ if (field.isRepeated()) {
+ @SuppressWarnings("unchecked") final
+ List<Message> messageList = (List<Message>) getField(field);
+ for (final Message element : messageList) {
+ if (!element.isInitialized()) {
+ return false;
+ }
+ }
+ } else {
+ if (hasField(field) &&
+ !((Message) getField(field)).isInitialized()) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public final UnknownFieldSet getUnknownFields() {
+ return unknownFields;
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ protected boolean parseUnknownField(
+ final CodedInputStream input,
+ final UnknownFieldSet.Builder unknownFields,
+ final ExtensionRegistryLite extensionRegistry,
+ final int tag) throws IOException {
+ return unknownFields.mergeFieldFrom(tag, input);
+ }
+
+ /**
+ * Implementation of {@link BuilderParent} for giving to our children. This
+ * small inner class makes it so we don't publicly expose the BuilderParent
+ * methods.
+ */
+ private class BuilderParentImpl implements BuilderParent {
+
+ @Override
+ public void markDirty() {
+ onChanged();
+ }
+ }
+
+ /**
+ * Gets the {@link BuilderParent} for giving to our children.
+ * @return The builder parent for our children.
+ */
+ protected BuilderParent getParentForChildren() {
+ if (meAsParent == null) {
+ meAsParent = new BuilderParentImpl();
+ }
+ return meAsParent;
+ }
+
+ /**
+ * Called when a the builder or one of its nested children has changed
+ * and any parent should be notified of its invalidation.
+ */
+ protected final void onChanged() {
+ if (isClean && builderParent != null) {
+ builderParent.markDirty();
+
+ // Don't keep dispatching invalidations until build is called again.
+ isClean = false;
+ }
+ }
+
+ /**
+ * Gets the map field with the given field number. This method should be
+ * overridden in the generated message class if the message contains map
+ * fields.
+ *
+ * Unlike other field types, reflection support for map fields can't be
+ * implemented based on generated public API because we need to access a
+ * map field as a list in reflection API but the generated API only allows
+ * us to access it as a map. This method returns the underlying map field
+ * directly and thus enables us to access the map field as a list.
+ */
+ @SuppressWarnings({"unused", "rawtypes"})
+ protected MapField internalGetMapField(int fieldNumber) {
+ // Note that we can't use descriptor names here because this method will
+ // be called when descriptor is being initialized.
+ throw new RuntimeException(
+ "No map fields found in " + getClass().getName());
+ }
+
+ /** Like {@link #internalGetMapField} but return a mutable version. */
+ @SuppressWarnings({"unused", "rawtypes"})
+ protected MapField internalGetMutableMapField(int fieldNumber) {
+ // Note that we can't use descriptor names here because this method will
+ // be called when descriptor is being initialized.
+ throw new RuntimeException(
+ "No map fields found in " + getClass().getName());
+ }
+ }
+
+ // =================================================================
+ // Extensions-related stuff
+
+ public interface ExtendableMessageOrBuilder<
+ MessageType extends ExtendableMessage> extends MessageOrBuilder {
+ // Re-define for return type covariance.
+ @Override
+ Message getDefaultInstanceForType();
+
+ /** Check if a singular extension is present. */
+ <Type> boolean hasExtension(
+ ExtensionLite<MessageType, Type> extension);
+
+ /** Get the number of elements in a repeated extension. */
+ <Type> int getExtensionCount(
+ ExtensionLite<MessageType, List<Type>> extension);
+
+ /** Get the value of an extension. */
+ <Type> Type getExtension(
+ ExtensionLite<MessageType, Type> extension);
+
+ /** Get one element of a repeated extension. */
+ <Type> Type getExtension(
+ ExtensionLite<MessageType, List<Type>> extension,
+ int index);
+
+ /** Check if a singular extension is present. */
+ <Type> boolean hasExtension(
+ Extension<MessageType, Type> extension);
+ /** Check if a singular extension is present. */
+ <Type> boolean hasExtension(
+ GeneratedExtension<MessageType, Type> extension);
+ /** Get the number of elements in a repeated extension. */
+ <Type> int getExtensionCount(
+ Extension<MessageType, List<Type>> extension);
+ /** Get the number of elements in a repeated extension. */
+ <Type> int getExtensionCount(
+ GeneratedExtension<MessageType, List<Type>> extension);
+ /** Get the value of an extension. */
+ <Type> Type getExtension(
+ Extension<MessageType, Type> extension);
+ /** Get the value of an extension. */
+ <Type> Type getExtension(
+ GeneratedExtension<MessageType, Type> extension);
+ /** Get one element of a repeated extension. */
+ <Type> Type getExtension(
+ Extension<MessageType, List<Type>> extension,
+ int index);
+ /** Get one element of a repeated extension. */
+ <Type> Type getExtension(
+ GeneratedExtension<MessageType, List<Type>> extension,
+ int index);
+ }
+
+ /**
+ * Generated message classes for message types that contain extension ranges
+ * subclass this.
+ *
+ * <p>This class implements type-safe accessors for extensions. They
+ * implement all the same operations that you can do with normal fields --
+ * e.g. "has", "get", and "getCount" -- but for extensions. The extensions
+ * are identified using instances of the class {@link GeneratedExtension};
+ * the protocol compiler generates a static instance of this class for every
+ * extension in its input. Through the magic of generics, all is made
+ * type-safe.
+ *
+ * <p>For example, imagine you have the {@code .proto} file:
+ *
+ * <pre>
+ * option java_class = "MyProto";
+ *
+ * message Foo {
+ * extensions 1000 to max;
+ * }
+ *
+ * extend Foo {
+ * optional int32 bar;
+ * }
+ * </pre>
+ *
+ * <p>Then you might write code like:
+ *
+ * <pre>
+ * MyProto.Foo foo = getFoo();
+ * int i = foo.getExtension(MyProto.bar);
+ * </pre>
+ *
+ * <p>See also {@link ExtendableBuilder}.
+ */
+ public abstract static class ExtendableMessage<
+ MessageType extends ExtendableMessage>
+ extends GeneratedMessageV3
+ implements ExtendableMessageOrBuilder<MessageType> {
+
+ private static final long serialVersionUID = 1L;
+
+ private final FieldSet<FieldDescriptor> extensions;
+
+ protected ExtendableMessage() {
+ this.extensions = FieldSet.newFieldSet();
+ }
+
+ protected ExtendableMessage(
+ ExtendableBuilder<MessageType, ?> builder) {
+ super(builder);
+ this.extensions = builder.buildExtensions();
+ }
+
+ private void verifyExtensionContainingType(
+ final Extension<MessageType, ?> extension) {
+ if (extension.getDescriptor().getContainingType() !=
+ getDescriptorForType()) {
+ // This can only happen if someone uses unchecked operations.
+ throw new IllegalArgumentException(
+ "Extension is for type \"" +
+ extension.getDescriptor().getContainingType().getFullName() +
+ "\" which does not match message type \"" +
+ getDescriptorForType().getFullName() + "\".");
+ }
+ }
+
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ return extensions.hasField(extension.getDescriptor());
+ }
+
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final ExtensionLite<MessageType, List<Type>> extensionLite) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ return extensions.getRepeatedFieldCount(descriptor);
+ }
+
+ /** Get the value of an extension. */
+ @Override
+ @SuppressWarnings("unchecked")
+ public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ FieldDescriptor descriptor = extension.getDescriptor();
+ final Object value = extensions.getField(descriptor);
+ if (value == null) {
+ if (descriptor.isRepeated()) {
+ return (Type) Collections.emptyList();
+ } else if (descriptor.getJavaType() ==
+ FieldDescriptor.JavaType.MESSAGE) {
+ return (Type) extension.getMessageDefaultInstance();
+ } else {
+ return (Type) extension.fromReflectionType(
+ descriptor.getDefaultValue());
+ }
+ } else {
+ return (Type) extension.fromReflectionType(value);
+ }
+ }
+
+ /** Get one element of a repeated extension. */
+ @Override
+ @SuppressWarnings("unchecked")
+ public final <Type> Type getExtension(
+ final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ FieldDescriptor descriptor = extension.getDescriptor();
+ return (Type) extension.singularFromReflectionType(
+ extensions.getRepeatedField(descriptor, index));
+ }
+
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(final Extension<MessageType, Type> extension) {
+ return hasExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(
+ final GeneratedExtension<MessageType, Type> extension) {
+ return hasExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final Extension<MessageType, List<Type>> extension) {
+ return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
+ }
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final GeneratedExtension<MessageType, List<Type>> extension) {
+ return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(final Extension<MessageType, Type> extension) {
+ return getExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final GeneratedExtension<MessageType, Type> extension) {
+ return getExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get one element of a repeated extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final Extension<MessageType, List<Type>> extension, final int index) {
+ return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
+ }
+ /** Get one element of a repeated extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final GeneratedExtension<MessageType, List<Type>> extension, final int index) {
+ return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
+ }
+
+ /** Called by subclasses to check if all extensions are initialized. */
+ protected boolean extensionsAreInitialized() {
+ return extensions.isInitialized();
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return super.isInitialized() && extensionsAreInitialized();
+ }
+
+ @Override
+ protected boolean parseUnknownField(
+ CodedInputStream input,
+ UnknownFieldSet.Builder unknownFields,
+ ExtensionRegistryLite extensionRegistry,
+ int tag) throws IOException {
+ return MessageReflection.mergeFieldFrom(
+ input, unknownFields, extensionRegistry, getDescriptorForType(),
+ new MessageReflection.ExtensionAdapter(extensions), tag);
+ }
+
+
+ /**
+ * Used by parsing constructors in generated classes.
+ */
+ @Override
+ protected void makeExtensionsImmutable() {
+ extensions.makeImmutable();
+ }
+
+ /**
+ * Used by subclasses to serialize extensions. Extension ranges may be
+ * interleaved with field numbers, but we must write them in canonical
+ * (sorted by field number) order. ExtensionWriter helps us write
+ * individual ranges of extensions at once.
+ */
+ protected class ExtensionWriter {
+ // Imagine how much simpler this code would be if Java iterators had
+ // a way to get the next element without advancing the iterator.
+
+ private final Iterator<Map.Entry<FieldDescriptor, Object>> iter =
+ extensions.iterator();
+ private Map.Entry<FieldDescriptor, Object> next;
+ private final boolean messageSetWireFormat;
+
+ private ExtensionWriter(final boolean messageSetWireFormat) {
+ if (iter.hasNext()) {
+ next = iter.next();
+ }
+ this.messageSetWireFormat = messageSetWireFormat;
+ }
+
+ public void writeUntil(final int end, final CodedOutputStream output)
+ throws IOException {
+ while (next != null && next.getKey().getNumber() < end) {
+ FieldDescriptor descriptor = next.getKey();
+ if (messageSetWireFormat && descriptor.getLiteJavaType() ==
+ WireFormat.JavaType.MESSAGE &&
+ !descriptor.isRepeated()) {
+ if (next instanceof LazyField.LazyEntry<?>) {
+ output.writeRawMessageSetExtension(descriptor.getNumber(),
+ ((LazyField.LazyEntry<?>) next).getField().toByteString());
+ } else {
+ output.writeMessageSetExtension(descriptor.getNumber(),
+ (Message) next.getValue());
+ }
+ } else {
+ // TODO(xiangl): Taken care of following code, it may cause
+ // problem when we use LazyField for normal fields/extensions.
+ // Due to the optional field can be duplicated at the end of
+ // serialized bytes, which will make the serialized size change
+ // after lazy field parsed. So when we use LazyField globally,
+ // we need to change the following write method to write cached
+ // bytes directly rather than write the parsed message.
+ FieldSet.writeField(descriptor, next.getValue(), output);
+ }
+ if (iter.hasNext()) {
+ next = iter.next();
+ } else {
+ next = null;
+ }
+ }
+ }
+ }
+
+ protected ExtensionWriter newExtensionWriter() {
+ return new ExtensionWriter(false);
+ }
+ protected ExtensionWriter newMessageSetExtensionWriter() {
+ return new ExtensionWriter(true);
+ }
+
+ /** Called by subclasses to compute the size of extensions. */
+ protected int extensionsSerializedSize() {
+ return extensions.getSerializedSize();
+ }
+ protected int extensionsSerializedSizeAsMessageSet() {
+ return extensions.getMessageSetSerializedSize();
+ }
+
+ // ---------------------------------------------------------------
+ // Reflection
+
+ protected Map<FieldDescriptor, Object> getExtensionFields() {
+ return extensions.getAllFields();
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ final Map<FieldDescriptor, Object> result =
+ super.getAllFieldsMutable(/* getBytesForString = */ false);
+ result.putAll(getExtensionFields());
+ return Collections.unmodifiableMap(result);
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFieldsRaw() {
+ final Map<FieldDescriptor, Object> result =
+ super.getAllFieldsMutable(/* getBytesForString = */ false);
+ result.putAll(getExtensionFields());
+ return Collections.unmodifiableMap(result);
+ }
+
+ @Override
+ public boolean hasField(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.hasField(field);
+ } else {
+ return super.hasField(field);
+ }
+ }
+
+ @Override
+ public Object getField(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ final Object value = extensions.getField(field);
+ if (value == null) {
+ if (field.isRepeated()) {
+ return Collections.emptyList();
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ // Lacking an ExtensionRegistry, we have no way to determine the
+ // extension's real type, so we return a DynamicMessage.
+ return DynamicMessage.getDefaultInstance(field.getMessageType());
+ } else {
+ return field.getDefaultValue();
+ }
+ } else {
+ return value;
+ }
+ } else {
+ return super.getField(field);
+ }
+ }
+
+ @Override
+ public int getRepeatedFieldCount(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.getRepeatedFieldCount(field);
+ } else {
+ return super.getRepeatedFieldCount(field);
+ }
+ }
+
+ @Override
+ public Object getRepeatedField(final FieldDescriptor field,
+ final int index) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.getRepeatedField(field, index);
+ } else {
+ return super.getRepeatedField(field, index);
+ }
+ }
+
+ private void verifyContainingType(final FieldDescriptor field) {
+ if (field.getContainingType() != getDescriptorForType()) {
+ throw new IllegalArgumentException(
+ "FieldDescriptor does not match message type.");
+ }
+ }
+ }
+
+ /**
+ * Generated message builders for message types that contain extension ranges
+ * subclass this.
+ *
+ * <p>This class implements type-safe accessors for extensions. They
+ * implement all the same operations that you can do with normal fields --
+ * e.g. "get", "set", and "add" -- but for extensions. The extensions are
+ * identified using instances of the class {@link GeneratedExtension}; the
+ * protocol compiler generates a static instance of this class for every
+ * extension in its input. Through the magic of generics, all is made
+ * type-safe.
+ *
+ * <p>For example, imagine you have the {@code .proto} file:
+ *
+ * <pre>
+ * option java_class = "MyProto";
+ *
+ * message Foo {
+ * extensions 1000 to max;
+ * }
+ *
+ * extend Foo {
+ * optional int32 bar;
+ * }
+ * </pre>
+ *
+ * <p>Then you might write code like:
+ *
+ * <pre>
+ * MyProto.Foo foo =
+ * MyProto.Foo.newBuilder()
+ * .setExtension(MyProto.bar, 123)
+ * .build();
+ * </pre>
+ *
+ * <p>See also {@link ExtendableMessage}.
+ */
+ @SuppressWarnings("unchecked")
+ public abstract static class ExtendableBuilder<
+ MessageType extends ExtendableMessage,
+ BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+ extends Builder<BuilderType>
+ implements ExtendableMessageOrBuilder<MessageType> {
+
+ private FieldSet<FieldDescriptor> extensions = FieldSet.emptySet();
+
+ protected ExtendableBuilder() {}
+
+ protected ExtendableBuilder(
+ BuilderParent parent) {
+ super(parent);
+ }
+
+ // For immutable message conversion.
+ void internalSetExtensionSet(FieldSet<FieldDescriptor> extensions) {
+ this.extensions = extensions;
+ }
+
+ @Override
+ public BuilderType clear() {
+ extensions = FieldSet.emptySet();
+ return super.clear();
+ }
+
+ // This is implemented here only to work around an apparent bug in the
+ // Java compiler and/or build system. See bug #1898463. The mere presence
+ // of this clone() implementation makes it go away.
+ @Override
+ public BuilderType clone() {
+ return super.clone();
+ }
+
+ private void ensureExtensionsIsMutable() {
+ if (extensions.isImmutable()) {
+ extensions = extensions.clone();
+ }
+ }
+
+ private void verifyExtensionContainingType(
+ final Extension<MessageType, ?> extension) {
+ if (extension.getDescriptor().getContainingType() !=
+ getDescriptorForType()) {
+ // This can only happen if someone uses unchecked operations.
+ throw new IllegalArgumentException(
+ "Extension is for type \"" +
+ extension.getDescriptor().getContainingType().getFullName() +
+ "\" which does not match message type \"" +
+ getDescriptorForType().getFullName() + "\".");
+ }
+ }
+
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ return extensions.hasField(extension.getDescriptor());
+ }
+
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final ExtensionLite<MessageType, List<Type>> extensionLite) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ return extensions.getRepeatedFieldCount(descriptor);
+ }
+
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ FieldDescriptor descriptor = extension.getDescriptor();
+ final Object value = extensions.getField(descriptor);
+ if (value == null) {
+ if (descriptor.isRepeated()) {
+ return (Type) Collections.emptyList();
+ } else if (descriptor.getJavaType() ==
+ FieldDescriptor.JavaType.MESSAGE) {
+ return (Type) extension.getMessageDefaultInstance();
+ } else {
+ return (Type) extension.fromReflectionType(
+ descriptor.getDefaultValue());
+ }
+ } else {
+ return (Type) extension.fromReflectionType(value);
+ }
+ }
+
+ /** Get one element of a repeated extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ FieldDescriptor descriptor = extension.getDescriptor();
+ return (Type) extension.singularFromReflectionType(
+ extensions.getRepeatedField(descriptor, index));
+ }
+
+ /** Set the value of an extension. */
+ public final <Type> BuilderType setExtension(
+ final ExtensionLite<MessageType, Type> extensionLite,
+ final Type value) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ ensureExtensionsIsMutable();
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ extensions.setField(descriptor, extension.toReflectionType(value));
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ /** Set the value of one element of a repeated extension. */
+ public final <Type> BuilderType setExtension(
+ final ExtensionLite<MessageType, List<Type>> extensionLite,
+ final int index, final Type value) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ ensureExtensionsIsMutable();
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ extensions.setRepeatedField(
+ descriptor, index,
+ extension.singularToReflectionType(value));
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ /** Append a value to a repeated extension. */
+ public final <Type> BuilderType addExtension(
+ final ExtensionLite<MessageType, List<Type>> extensionLite,
+ final Type value) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ ensureExtensionsIsMutable();
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ extensions.addRepeatedField(
+ descriptor, extension.singularToReflectionType(value));
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ /** Clear an extension. */
+ public final <Type> BuilderType clearExtension(
+ final ExtensionLite<MessageType, ?> extensionLite) {
+ Extension<MessageType, ?> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ ensureExtensionsIsMutable();
+ extensions.clearField(extension.getDescriptor());
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(final Extension<MessageType, Type> extension) {
+ return hasExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(
+ final GeneratedExtension<MessageType, Type> extension) {
+ return hasExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final Extension<MessageType, List<Type>> extension) {
+ return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
+ }
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final GeneratedExtension<MessageType, List<Type>> extension) {
+ return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(final Extension<MessageType, Type> extension) {
+ return getExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final GeneratedExtension<MessageType, Type> extension) {
+ return getExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final Extension<MessageType, List<Type>> extension, final int index) {
+ return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final GeneratedExtension<MessageType, List<Type>> extension, final int index) {
+ return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
+ }
+ /** Set the value of an extension. */
+ public final <Type> BuilderType setExtension(
+ final Extension<MessageType, Type> extension, final Type value) {
+ return setExtension((ExtensionLite<MessageType, Type>) extension, value);
+ }
+ /** Set the value of an extension. */
+ public <Type> BuilderType setExtension(
+ final GeneratedExtension<MessageType, Type> extension, final Type value) {
+ return setExtension((ExtensionLite<MessageType, Type>) extension, value);
+ }
+ /** Set the value of one element of a repeated extension. */
+ public final <Type> BuilderType setExtension(
+ final Extension<MessageType, List<Type>> extension,
+ final int index, final Type value) {
+ return setExtension((ExtensionLite<MessageType, List<Type>>) extension, index, value);
+ }
+ /** Set the value of one element of a repeated extension. */
+ public <Type> BuilderType setExtension(
+ final GeneratedExtension<MessageType, List<Type>> extension,
+ final int index, final Type value) {
+ return setExtension((ExtensionLite<MessageType, List<Type>>) extension, index, value);
+ }
+ /** Append a value to a repeated extension. */
+ public final <Type> BuilderType addExtension(
+ final Extension<MessageType, List<Type>> extension, final Type value) {
+ return addExtension((ExtensionLite<MessageType, List<Type>>) extension, value);
+ }
+ /** Append a value to a repeated extension. */
+ public <Type> BuilderType addExtension(
+ final GeneratedExtension<MessageType, List<Type>> extension, final Type value) {
+ return addExtension((ExtensionLite<MessageType, List<Type>>) extension, value);
+ }
+ /** Clear an extension. */
+ public final <Type> BuilderType clearExtension(
+ final Extension<MessageType, ?> extension) {
+ return clearExtension((ExtensionLite<MessageType, ?>) extension);
+ }
+ /** Clear an extension. */
+ public <Type> BuilderType clearExtension(
+ final GeneratedExtension<MessageType, ?> extension) {
+ return clearExtension((ExtensionLite<MessageType, ?>) extension);
+ }
+
+ /** Called by subclasses to check if all extensions are initialized. */
+ protected boolean extensionsAreInitialized() {
+ return extensions.isInitialized();
+ }
+
+ /**
+ * Called by the build code path to create a copy of the extensions for
+ * building the message.
+ */
+ private FieldSet<FieldDescriptor> buildExtensions() {
+ extensions.makeImmutable();
+ return extensions;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return super.isInitialized() && extensionsAreInitialized();
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field or an extension.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ @Override
+ protected boolean parseUnknownField(
+ final CodedInputStream input,
+ final UnknownFieldSet.Builder unknownFields,
+ final ExtensionRegistryLite extensionRegistry,
+ final int tag) throws IOException {
+ return MessageReflection.mergeFieldFrom(
+ input, unknownFields, extensionRegistry, getDescriptorForType(),
+ new MessageReflection.BuilderAdapter(this), tag);
+ }
+
+ // ---------------------------------------------------------------
+ // Reflection
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable();
+ result.putAll(extensions.getAllFields());
+ return Collections.unmodifiableMap(result);
+ }
+
+ @Override
+ public Object getField(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ final Object value = extensions.getField(field);
+ if (value == null) {
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ // Lacking an ExtensionRegistry, we have no way to determine the
+ // extension's real type, so we return a DynamicMessage.
+ return DynamicMessage.getDefaultInstance(field.getMessageType());
+ } else {
+ return field.getDefaultValue();
+ }
+ } else {
+ return value;
+ }
+ } else {
+ return super.getField(field);
+ }
+ }
+
+ @Override
+ public int getRepeatedFieldCount(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.getRepeatedFieldCount(field);
+ } else {
+ return super.getRepeatedFieldCount(field);
+ }
+ }
+
+ @Override
+ public Object getRepeatedField(final FieldDescriptor field,
+ final int index) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.getRepeatedField(field, index);
+ } else {
+ return super.getRepeatedField(field, index);
+ }
+ }
+
+ @Override
+ public boolean hasField(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.hasField(field);
+ } else {
+ return super.hasField(field);
+ }
+ }
+
+ @Override
+ public BuilderType setField(final FieldDescriptor field,
+ final Object value) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ ensureExtensionsIsMutable();
+ extensions.setField(field, value);
+ onChanged();
+ return (BuilderType) this;
+ } else {
+ return super.setField(field, value);
+ }
+ }
+
+ @Override
+ public BuilderType clearField(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ ensureExtensionsIsMutable();
+ extensions.clearField(field);
+ onChanged();
+ return (BuilderType) this;
+ } else {
+ return super.clearField(field);
+ }
+ }
+
+ @Override
+ public BuilderType setRepeatedField(final FieldDescriptor field,
+ final int index, final Object value) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ ensureExtensionsIsMutable();
+ extensions.setRepeatedField(field, index, value);
+ onChanged();
+ return (BuilderType) this;
+ } else {
+ return super.setRepeatedField(field, index, value);
+ }
+ }
+
+ @Override
+ public BuilderType addRepeatedField(final FieldDescriptor field,
+ final Object value) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ ensureExtensionsIsMutable();
+ extensions.addRepeatedField(field, value);
+ onChanged();
+ return (BuilderType) this;
+ } else {
+ return super.addRepeatedField(field, value);
+ }
+ }
+
+ protected final void mergeExtensionFields(final ExtendableMessage other) {
+ ensureExtensionsIsMutable();
+ extensions.mergeFrom(other.extensions);
+ onChanged();
+ }
+
+ private void verifyContainingType(final FieldDescriptor field) {
+ if (field.getContainingType() != getDescriptorForType()) {
+ throw new IllegalArgumentException(
+ "FieldDescriptor does not match message type.");
+ }
+ }
+ }
+
+ // -----------------------------------------------------------------
+
+ /**
+ * Gets the descriptor for an extension. The implementation depends on whether
+ * the extension is scoped in the top level of a file or scoped in a Message.
+ */
+ static interface ExtensionDescriptorRetriever {
+ FieldDescriptor getDescriptor();
+ }
+
+ private abstract static class CachedDescriptorRetriever
+ implements ExtensionDescriptorRetriever {
+ private volatile FieldDescriptor descriptor;
+ protected abstract FieldDescriptor loadDescriptor();
+
+ @Override
+ public FieldDescriptor getDescriptor() {
+ if (descriptor == null) {
+ synchronized (this) {
+ if (descriptor == null) {
+ descriptor = loadDescriptor();
+ }
+ }
+ }
+ return descriptor;
+ }
+ }
+
+ // =================================================================
+
+ /** Calls Class.getMethod and throws a RuntimeException if it fails. */
+ @SuppressWarnings("unchecked")
+ private static Method getMethodOrDie(
+ final Class clazz, final String name, final Class... params) {
+ try {
+ return clazz.getMethod(name, params);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(
+ "Generated message class \"" + clazz.getName() +
+ "\" missing method \"" + name + "\".", e);
+ }
+ }
+
+ /** Calls invoke and throws a RuntimeException if it fails. */
+ private static Object invokeOrDie(
+ final Method method, final Object object, final Object... params) {
+ try {
+ return method.invoke(object, params);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(
+ "Couldn't use Java reflection to implement protocol message " +
+ "reflection.", e);
+ } catch (InvocationTargetException e) {
+ final Throwable cause = e.getCause();
+ if (cause instanceof RuntimeException) {
+ throw (RuntimeException) cause;
+ } else if (cause instanceof Error) {
+ throw (Error) cause;
+ } else {
+ throw new RuntimeException(
+ "Unexpected exception thrown by generated accessor method.", cause);
+ }
+ }
+ }
+
+ /**
+ * Gets the map field with the given field number. This method should be
+ * overridden in the generated message class if the message contains map
+ * fields.
+ *
+ * Unlike other field types, reflection support for map fields can't be
+ * implemented based on generated public API because we need to access a
+ * map field as a list in reflection API but the generated API only allows
+ * us to access it as a map. This method returns the underlying map field
+ * directly and thus enables us to access the map field as a list.
+ */
+ @SuppressWarnings({"rawtypes", "unused"})
+ protected MapField internalGetMapField(int fieldNumber) {
+ // Note that we can't use descriptor names here because this method will
+ // be called when descriptor is being initialized.
+ throw new RuntimeException(
+ "No map fields found in " + getClass().getName());
+ }
+
+ /**
+ * Users should ignore this class. This class provides the implementation
+ * with access to the fields of a message object using Java reflection.
+ */
+ public static final class FieldAccessorTable {
+
+ /**
+ * Construct a FieldAccessorTable for a particular message class. Only
+ * one FieldAccessorTable should ever be constructed per class.
+ *
+ * @param descriptor The type's descriptor.
+ * @param camelCaseNames The camelcase names of all fields in the message.
+ * These are used to derive the accessor method names.
+ * @param messageClass The message type.
+ * @param builderClass The builder type.
+ */
+ public FieldAccessorTable(
+ final Descriptor descriptor,
+ final String[] camelCaseNames,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass) {
+ this(descriptor, camelCaseNames);
+ ensureFieldAccessorsInitialized(messageClass, builderClass);
+ }
+
+ /**
+ * Construct a FieldAccessorTable for a particular message class without
+ * initializing FieldAccessors.
+ */
+ public FieldAccessorTable(
+ final Descriptor descriptor,
+ final String[] camelCaseNames) {
+ this.descriptor = descriptor;
+ this.camelCaseNames = camelCaseNames;
+ fields = new FieldAccessor[descriptor.getFields().size()];
+ oneofs = new OneofAccessor[descriptor.getOneofs().size()];
+ initialized = false;
+ }
+
+ private boolean isMapFieldEnabled(FieldDescriptor field) {
+ boolean result = true;
+ return result;
+ }
+
+ /**
+ * Ensures the field accessors are initialized. This method is thread-safe.
+ *
+ * @param messageClass The message type.
+ * @param builderClass The builder type.
+ * @return this
+ */
+ public FieldAccessorTable ensureFieldAccessorsInitialized(
+ Class<? extends GeneratedMessageV3> messageClass,
+ Class<? extends Builder> builderClass) {
+ if (initialized) { return this; }
+ synchronized (this) {
+ if (initialized) { return this; }
+ int fieldsSize = fields.length;
+ for (int i = 0; i < fieldsSize; i++) {
+ FieldDescriptor field = descriptor.getFields().get(i);
+ String containingOneofCamelCaseName = null;
+ if (field.getContainingOneof() != null) {
+ containingOneofCamelCaseName =
+ camelCaseNames[fieldsSize + field.getContainingOneof().getIndex()];
+ }
+ if (field.isRepeated()) {
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ if (field.isMapField() && isMapFieldEnabled(field)) {
+ fields[i] = new MapFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ } else {
+ fields[i] = new RepeatedMessageFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ }
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+ fields[i] = new RepeatedEnumFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ } else {
+ fields[i] = new RepeatedFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ }
+ } else {
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ fields[i] = new SingularMessageFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass,
+ containingOneofCamelCaseName);
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+ fields[i] = new SingularEnumFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass,
+ containingOneofCamelCaseName);
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.STRING) {
+ fields[i] = new SingularStringFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass,
+ containingOneofCamelCaseName);
+ } else {
+ fields[i] = new SingularFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass,
+ containingOneofCamelCaseName);
+ }
+ }
+ }
+
+ int oneofsSize = oneofs.length;
+ for (int i = 0; i < oneofsSize; i++) {
+ oneofs[i] = new OneofAccessor(
+ descriptor, camelCaseNames[i + fieldsSize],
+ messageClass, builderClass);
+ }
+ initialized = true;
+ camelCaseNames = null;
+ return this;
+ }
+ }
+
+ private final Descriptor descriptor;
+ private final FieldAccessor[] fields;
+ private String[] camelCaseNames;
+ private final OneofAccessor[] oneofs;
+ private volatile boolean initialized;
+
+ /** Get the FieldAccessor for a particular field. */
+ private FieldAccessor getField(final FieldDescriptor field) {
+ if (field.getContainingType() != descriptor) {
+ throw new IllegalArgumentException(
+ "FieldDescriptor does not match message type.");
+ } else if (field.isExtension()) {
+ // If this type had extensions, it would subclass ExtendableMessage,
+ // which overrides the reflection interface to handle extensions.
+ throw new IllegalArgumentException(
+ "This type does not have extensions.");
+ }
+ return fields[field.getIndex()];
+ }
+
+ /** Get the OneofAccessor for a particular oneof. */
+ private OneofAccessor getOneof(final OneofDescriptor oneof) {
+ if (oneof.getContainingType() != descriptor) {
+ throw new IllegalArgumentException(
+ "OneofDescriptor does not match message type.");
+ }
+ return oneofs[oneof.getIndex()];
+ }
+
+ /**
+ * Abstract interface that provides access to a single field. This is
+ * implemented differently depending on the field type and cardinality.
+ */
+ private interface FieldAccessor {
+ Object get(GeneratedMessageV3 message);
+ Object get(GeneratedMessageV3.Builder builder);
+ Object getRaw(GeneratedMessageV3 message);
+ Object getRaw(GeneratedMessageV3.Builder builder);
+ void set(Builder builder, Object value);
+ Object getRepeated(GeneratedMessageV3 message, int index);
+ Object getRepeated(GeneratedMessageV3.Builder builder, int index);
+ Object getRepeatedRaw(GeneratedMessageV3 message, int index);
+ Object getRepeatedRaw(GeneratedMessageV3.Builder builder, int index);
+ void setRepeated(Builder builder,
+ int index, Object value);
+ void addRepeated(Builder builder, Object value);
+ boolean has(GeneratedMessageV3 message);
+ boolean has(GeneratedMessageV3.Builder builder);
+ int getRepeatedCount(GeneratedMessageV3 message);
+ int getRepeatedCount(GeneratedMessageV3.Builder builder);
+ void clear(Builder builder);
+ Message.Builder newBuilder();
+ Message.Builder getBuilder(GeneratedMessageV3.Builder builder);
+ Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder,
+ int index);
+ }
+
+ /** OneofAccessor provides access to a single oneof. */
+ private static class OneofAccessor {
+ OneofAccessor(
+ final Descriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass) {
+ this.descriptor = descriptor;
+ caseMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Case");
+ caseMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Case");
+ clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
+ }
+
+ private final Descriptor descriptor;
+ private final Method caseMethod;
+ private final Method caseMethodBuilder;
+ private final Method clearMethod;
+
+ public boolean has(final GeneratedMessageV3 message) {
+ if (((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber() == 0) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean has(GeneratedMessageV3.Builder builder) {
+ if (((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber() == 0) {
+ return false;
+ }
+ return true;
+ }
+
+ public FieldDescriptor get(final GeneratedMessageV3 message) {
+ int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
+ if (fieldNumber > 0) {
+ return descriptor.findFieldByNumber(fieldNumber);
+ }
+ return null;
+ }
+
+ public FieldDescriptor get(GeneratedMessageV3.Builder builder) {
+ int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
+ if (fieldNumber > 0) {
+ return descriptor.findFieldByNumber(fieldNumber);
+ }
+ return null;
+ }
+
+ public void clear(final Builder builder) {
+ invokeOrDie(clearMethod, builder);
+ }
+ }
+
+ private static boolean supportFieldPresence(FileDescriptor file) {
+ return file.getSyntax() == FileDescriptor.Syntax.PROTO2;
+ }
+
+ // ---------------------------------------------------------------
+
+ private static class SingularFieldAccessor implements FieldAccessor {
+ SingularFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass,
+ final String containingOneofCamelCaseName) {
+ field = descriptor;
+ isOneofField = descriptor.getContainingOneof() != null;
+ hasHasMethod = supportFieldPresence(descriptor.getFile())
+ || (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE);
+ getMethod = getMethodOrDie(messageClass, "get" + camelCaseName);
+ getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName);
+ type = getMethod.getReturnType();
+ setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type);
+ hasMethod =
+ hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null;
+ hasMethodBuilder =
+ hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName) : null;
+ clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
+ caseMethod = isOneofField ? getMethodOrDie(
+ messageClass, "get" + containingOneofCamelCaseName + "Case") : null;
+ caseMethodBuilder = isOneofField ? getMethodOrDie(
+ builderClass, "get" + containingOneofCamelCaseName + "Case") : null;
+ }
+
+ // Note: We use Java reflection to call public methods rather than
+ // access private fields directly as this avoids runtime security
+ // checks.
+ protected final Class<?> type;
+ protected final Method getMethod;
+ protected final Method getMethodBuilder;
+ protected final Method setMethod;
+ protected final Method hasMethod;
+ protected final Method hasMethodBuilder;
+ protected final Method clearMethod;
+ protected final Method caseMethod;
+ protected final Method caseMethodBuilder;
+ protected final FieldDescriptor field;
+ protected final boolean isOneofField;
+ protected final boolean hasHasMethod;
+
+ private int getOneofFieldNumber(final GeneratedMessageV3 message) {
+ return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
+ }
+
+ private int getOneofFieldNumber(final GeneratedMessageV3.Builder builder) {
+ return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
+ }
+
+ @Override
+ public Object get(final GeneratedMessageV3 message) {
+ return invokeOrDie(getMethod, message);
+ }
+ @Override
+ public Object get(GeneratedMessageV3.Builder builder) {
+ return invokeOrDie(getMethodBuilder, builder);
+ }
+ @Override
+ public Object getRaw(final GeneratedMessageV3 message) {
+ return get(message);
+ }
+ @Override
+ public Object getRaw(GeneratedMessageV3.Builder builder) {
+ return get(builder);
+ }
+ @Override
+ public void set(final Builder builder, final Object value) {
+ invokeOrDie(setMethod, builder, value);
+ }
+ @Override
+ public Object getRepeated(final GeneratedMessageV3 message, final int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedField() called on a singular field.");
+ }
+ @Override
+ public Object getRepeatedRaw(final GeneratedMessageV3 message, final int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldRaw() called on a singular field.");
+ }
+ @Override
+ public Object getRepeated(GeneratedMessageV3.Builder builder, int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedField() called on a singular field.");
+ }
+ @Override
+ public Object getRepeatedRaw(GeneratedMessageV3.Builder builder, int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldRaw() called on a singular field.");
+ }
+ @Override
+ public void setRepeated(final Builder builder, final int index, final Object value) {
+ throw new UnsupportedOperationException(
+ "setRepeatedField() called on a singular field.");
+ }
+ @Override
+ public void addRepeated(final Builder builder, final Object value) {
+ throw new UnsupportedOperationException(
+ "addRepeatedField() called on a singular field.");
+ }
+ @Override
+ public boolean has(final GeneratedMessageV3 message) {
+ if (!hasHasMethod) {
+ if (isOneofField) {
+ return getOneofFieldNumber(message) == field.getNumber();
+ }
+ return !get(message).equals(field.getDefaultValue());
+ }
+ return (Boolean) invokeOrDie(hasMethod, message);
+ }
+ @Override
+ public boolean has(GeneratedMessageV3.Builder builder) {
+ if (!hasHasMethod) {
+ if (isOneofField) {
+ return getOneofFieldNumber(builder) == field.getNumber();
+ }
+ return !get(builder).equals(field.getDefaultValue());
+ }
+ return (Boolean) invokeOrDie(hasMethodBuilder, builder);
+ }
+ @Override
+ public int getRepeatedCount(final GeneratedMessageV3 message) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldSize() called on a singular field.");
+ }
+ @Override
+ public int getRepeatedCount(GeneratedMessageV3.Builder builder) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldSize() called on a singular field.");
+ }
+ @Override
+ public void clear(final Builder builder) {
+ invokeOrDie(clearMethod, builder);
+ }
+ @Override
+ public Message.Builder newBuilder() {
+ throw new UnsupportedOperationException(
+ "newBuilderForField() called on a non-Message type.");
+ }
+ @Override
+ public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) {
+ throw new UnsupportedOperationException(
+ "getFieldBuilder() called on a non-Message type.");
+ }
+ @Override
+ public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldBuilder() called on a non-Message type.");
+ }
+ }
+
+ private static class RepeatedFieldAccessor implements FieldAccessor {
+ protected final Class type;
+ protected final Method getMethod;
+ protected final Method getMethodBuilder;
+ protected final Method getRepeatedMethod;
+ protected final Method getRepeatedMethodBuilder;
+ protected final Method setRepeatedMethod;
+ protected final Method addRepeatedMethod;
+ protected final Method getCountMethod;
+ protected final Method getCountMethodBuilder;
+ protected final Method clearMethod;
+
+ RepeatedFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass) {
+ getMethod = getMethodOrDie(messageClass,
+ "get" + camelCaseName + "List");
+ getMethodBuilder = getMethodOrDie(builderClass,
+ "get" + camelCaseName + "List");
+ getRepeatedMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
+ getRepeatedMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE);
+ type = getRepeatedMethod.getReturnType();
+ setRepeatedMethod =
+ getMethodOrDie(builderClass, "set" + camelCaseName,
+ Integer.TYPE, type);
+ addRepeatedMethod =
+ getMethodOrDie(builderClass, "add" + camelCaseName, type);
+ getCountMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Count");
+ getCountMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Count");
+
+ clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
+ }
+
+ @Override
+ public Object get(final GeneratedMessageV3 message) {
+ return invokeOrDie(getMethod, message);
+ }
+ @Override
+ public Object get(GeneratedMessageV3.Builder builder) {
+ return invokeOrDie(getMethodBuilder, builder);
+ }
+ @Override
+ public Object getRaw(final GeneratedMessageV3 message) {
+ return get(message);
+ }
+ @Override
+ public Object getRaw(GeneratedMessageV3.Builder builder) {
+ return get(builder);
+ }
+ @Override
+ public void set(final Builder builder, final Object value) {
+ // Add all the elements individually. This serves two purposes:
+ // 1) Verifies that each element has the correct type.
+ // 2) Insures that the caller cannot modify the list later on and
+ // have the modifications be reflected in the message.
+ clear(builder);
+ for (final Object element : (List<?>) value) {
+ addRepeated(builder, element);
+ }
+ }
+ @Override
+ public Object getRepeated(final GeneratedMessageV3 message, final int index) {
+ return invokeOrDie(getRepeatedMethod, message, index);
+ }
+ @Override
+ public Object getRepeated(GeneratedMessageV3.Builder builder, int index) {
+ return invokeOrDie(getRepeatedMethodBuilder, builder, index);
+ }
+ @Override
+ public Object getRepeatedRaw(GeneratedMessageV3 message, int index) {
+ return getRepeated(message, index);
+ }
+ @Override
+ public Object getRepeatedRaw(GeneratedMessageV3.Builder builder, int index) {
+ return getRepeated(builder, index);
+ }
+ @Override
+ public void setRepeated(final Builder builder, final int index, final Object value) {
+ invokeOrDie(setRepeatedMethod, builder, index, value);
+ }
+ @Override
+ public void addRepeated(final Builder builder, final Object value) {
+ invokeOrDie(addRepeatedMethod, builder, value);
+ }
+ @Override
+ public boolean has(final GeneratedMessageV3 message) {
+ throw new UnsupportedOperationException(
+ "hasField() called on a repeated field.");
+ }
+ @Override
+ public boolean has(GeneratedMessageV3.Builder builder) {
+ throw new UnsupportedOperationException(
+ "hasField() called on a repeated field.");
+ }
+ @Override
+ public int getRepeatedCount(final GeneratedMessageV3 message) {
+ return (Integer) invokeOrDie(getCountMethod, message);
+ }
+ @Override
+ public int getRepeatedCount(GeneratedMessageV3.Builder builder) {
+ return (Integer) invokeOrDie(getCountMethodBuilder, builder);
+ }
+ @Override
+ public void clear(final Builder builder) {
+ invokeOrDie(clearMethod, builder);
+ }
+ @Override
+ public Message.Builder newBuilder() {
+ throw new UnsupportedOperationException(
+ "newBuilderForField() called on a non-Message type.");
+ }
+ @Override
+ public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) {
+ throw new UnsupportedOperationException(
+ "getFieldBuilder() called on a non-Message type.");
+ }
+ @Override
+ public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldBuilder() called on a non-Message type.");
+ }
+ }
+
+ private static class MapFieldAccessor implements FieldAccessor {
+ MapFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass) {
+ field = descriptor;
+ Method getDefaultInstanceMethod =
+ getMethodOrDie(messageClass, "getDefaultInstance");
+ MapField defaultMapField = getMapField(
+ (GeneratedMessageV3) invokeOrDie(getDefaultInstanceMethod, null));
+ mapEntryMessageDefaultInstance =
+ defaultMapField.getMapEntryMessageDefaultInstance();
+ }
+
+ private final FieldDescriptor field;
+ private final Message mapEntryMessageDefaultInstance;
+
+ private MapField<?, ?> getMapField(GeneratedMessageV3 message) {
+ return (MapField<?, ?>) message.internalGetMapField(field.getNumber());
+ }
+
+ private MapField<?, ?> getMapField(GeneratedMessageV3.Builder builder) {
+ return (MapField<?, ?>) builder.internalGetMapField(field.getNumber());
+ }
+
+ private MapField<?, ?> getMutableMapField(
+ GeneratedMessageV3.Builder builder) {
+ return (MapField<?, ?>) builder.internalGetMutableMapField(
+ field.getNumber());
+ }
+
+ @Override
+ public Object get(GeneratedMessageV3 message) {
+ List result = new ArrayList();
+ for (int i = 0; i < getRepeatedCount(message); i++) {
+ result.add(getRepeated(message, i));
+ }
+ return Collections.unmodifiableList(result);
+ }
+
+ @Override
+ public Object get(Builder builder) {
+ List result = new ArrayList();
+ for (int i = 0; i < getRepeatedCount(builder); i++) {
+ result.add(getRepeated(builder, i));
+ }
+ return Collections.unmodifiableList(result);
+ }
+
+ @Override
+ public Object getRaw(GeneratedMessageV3 message) {
+ return get(message);
+ }
+
+ @Override
+ public Object getRaw(GeneratedMessageV3.Builder builder) {
+ return get(builder);
+ }
+
+ @Override
+ public void set(Builder builder, Object value) {
+ clear(builder);
+ for (Object entry : (List) value) {
+ addRepeated(builder, entry);
+ }
+ }
+
+ @Override
+ public Object getRepeated(GeneratedMessageV3 message, int index) {
+ return getMapField(message).getList().get(index);
+ }
+
+ @Override
+ public Object getRepeated(Builder builder, int index) {
+ return getMapField(builder).getList().get(index);
+ }
+
+ @Override
+ public Object getRepeatedRaw(GeneratedMessageV3 message, int index) {
+ return getRepeated(message, index);
+ }
+
+ @Override
+ public Object getRepeatedRaw(Builder builder, int index) {
+ return getRepeated(builder, index);
+ }
+
+ @Override
+ public void setRepeated(Builder builder, int index, Object value) {
+ getMutableMapField(builder).getMutableList().set(index, (Message) value);
+ }
+
+ @Override
+ public void addRepeated(Builder builder, Object value) {
+ getMutableMapField(builder).getMutableList().add((Message) value);
+ }
+
+ @Override
+ public boolean has(GeneratedMessageV3 message) {
+ throw new UnsupportedOperationException(
+ "hasField() is not supported for repeated fields.");
+ }
+
+ @Override
+ public boolean has(Builder builder) {
+ throw new UnsupportedOperationException(
+ "hasField() is not supported for repeated fields.");
+ }
+
+ @Override
+ public int getRepeatedCount(GeneratedMessageV3 message) {
+ return getMapField(message).getList().size();
+ }
+
+ @Override
+ public int getRepeatedCount(Builder builder) {
+ return getMapField(builder).getList().size();
+ }
+
+ @Override
+ public void clear(Builder builder) {
+ getMutableMapField(builder).getMutableList().clear();
+ }
+
+ @Override
+ public com.google.protobuf.Message.Builder newBuilder() {
+ return mapEntryMessageDefaultInstance.newBuilderForType();
+ }
+
+ @Override
+ public com.google.protobuf.Message.Builder getBuilder(Builder builder) {
+ throw new UnsupportedOperationException(
+ "Nested builder not supported for map fields.");
+ }
+
+ @Override
+ public com.google.protobuf.Message.Builder getRepeatedBuilder(Builder builder, int index) {
+ throw new UnsupportedOperationException(
+ "Nested builder not supported for map fields.");
+ }
+ }
+
+ // ---------------------------------------------------------------
+
+ private static final class SingularEnumFieldAccessor
+ extends SingularFieldAccessor {
+ SingularEnumFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass,
+ final String containingOneofCamelCaseName) {
+ super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
+
+ enumDescriptor = descriptor.getEnumType();
+
+ valueOfMethod = getMethodOrDie(type, "valueOf",
+ EnumValueDescriptor.class);
+ getValueDescriptorMethod =
+ getMethodOrDie(type, "getValueDescriptor");
+
+ supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
+ if (supportUnknownEnumValue) {
+ getValueMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Value");
+ getValueMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Value");
+ setValueMethod =
+ getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class);
+ }
+ }
+
+ private EnumDescriptor enumDescriptor;
+
+ private Method valueOfMethod;
+ private Method getValueDescriptorMethod;
+
+ private boolean supportUnknownEnumValue;
+ private Method getValueMethod;
+ private Method getValueMethodBuilder;
+ private Method setValueMethod;
+
+ @Override
+ public Object get(final GeneratedMessageV3 message) {
+ if (supportUnknownEnumValue) {
+ int value = (Integer) invokeOrDie(getValueMethod, message);
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+ }
+ return invokeOrDie(getValueDescriptorMethod, super.get(message));
+ }
+
+ @Override
+ public Object get(final GeneratedMessageV3.Builder builder) {
+ if (supportUnknownEnumValue) {
+ int value = (Integer) invokeOrDie(getValueMethodBuilder, builder);
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+ }
+ return invokeOrDie(getValueDescriptorMethod, super.get(builder));
+ }
+
+ @Override
+ public void set(final Builder builder, final Object value) {
+ if (supportUnknownEnumValue) {
+ invokeOrDie(setValueMethod, builder,
+ ((EnumValueDescriptor) value).getNumber());
+ return;
+ }
+ super.set(builder, invokeOrDie(valueOfMethod, null, value));
+ }
+ }
+
+ private static final class RepeatedEnumFieldAccessor
+ extends RepeatedFieldAccessor {
+ RepeatedEnumFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass) {
+ super(descriptor, camelCaseName, messageClass, builderClass);
+
+ enumDescriptor = descriptor.getEnumType();
+
+ valueOfMethod = getMethodOrDie(type, "valueOf",
+ EnumValueDescriptor.class);
+ getValueDescriptorMethod =
+ getMethodOrDie(type, "getValueDescriptor");
+
+ supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
+ if (supportUnknownEnumValue) {
+ getRepeatedValueMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Value", int.class);
+ getRepeatedValueMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Value", int.class);
+ setRepeatedValueMethod =
+ getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class, int.class);
+ addRepeatedValueMethod =
+ getMethodOrDie(builderClass, "add" + camelCaseName + "Value", int.class);
+ }
+ }
+ private EnumDescriptor enumDescriptor;
+
+ private final Method valueOfMethod;
+ private final Method getValueDescriptorMethod;
+
+ private boolean supportUnknownEnumValue;
+ private Method getRepeatedValueMethod;
+ private Method getRepeatedValueMethodBuilder;
+ private Method setRepeatedValueMethod;
+ private Method addRepeatedValueMethod;
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object get(final GeneratedMessageV3 message) {
+ final List newList = new ArrayList();
+ final int size = getRepeatedCount(message);
+ for (int i = 0; i < size; i++) {
+ newList.add(getRepeated(message, i));
+ }
+ return Collections.unmodifiableList(newList);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object get(final GeneratedMessageV3.Builder builder) {
+ final List newList = new ArrayList();
+ final int size = getRepeatedCount(builder);
+ for (int i = 0; i < size; i++) {
+ newList.add(getRepeated(builder, i));
+ }
+ return Collections.unmodifiableList(newList);
+ }
+
+ @Override
+ public Object getRepeated(final GeneratedMessageV3 message,
+ final int index) {
+ if (supportUnknownEnumValue) {
+ int value = (Integer) invokeOrDie(getRepeatedValueMethod, message, index);
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+ }
+ return invokeOrDie(getValueDescriptorMethod,
+ super.getRepeated(message, index));
+ }
+ @Override
+ public Object getRepeated(final GeneratedMessageV3.Builder builder,
+ final int index) {
+ if (supportUnknownEnumValue) {
+ int value = (Integer) invokeOrDie(getRepeatedValueMethodBuilder, builder, index);
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+ }
+ return invokeOrDie(getValueDescriptorMethod,
+ super.getRepeated(builder, index));
+ }
+ @Override
+ public void setRepeated(final Builder builder,
+ final int index, final Object value) {
+ if (supportUnknownEnumValue) {
+ invokeOrDie(setRepeatedValueMethod, builder, index,
+ ((EnumValueDescriptor) value).getNumber());
+ return;
+ }
+ super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null,
+ value));
+ }
+ @Override
+ public void addRepeated(final Builder builder, final Object value) {
+ if (supportUnknownEnumValue) {
+ invokeOrDie(addRepeatedValueMethod, builder,
+ ((EnumValueDescriptor) value).getNumber());
+ return;
+ }
+ super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value));
+ }
+ }
+
+ // ---------------------------------------------------------------
+
+ /**
+ * Field accessor for string fields.
+ *
+ * <p>This class makes getFooBytes() and setFooBytes() available for
+ * reflection API so that reflection based serialize/parse functions can
+ * access the raw bytes of the field to preserve non-UTF8 bytes in the
+ * string.
+ *
+ * <p>This ensures the serialize/parse round-trip safety, which is important
+ * for servers which forward messages.
+ */
+ private static final class SingularStringFieldAccessor
+ extends SingularFieldAccessor {
+ SingularStringFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass,
+ final String containingOneofCamelCaseName) {
+ super(descriptor, camelCaseName, messageClass, builderClass,
+ containingOneofCamelCaseName);
+ getBytesMethod = getMethodOrDie(messageClass,
+ "get" + camelCaseName + "Bytes");
+ getBytesMethodBuilder = getMethodOrDie(builderClass,
+ "get" + camelCaseName + "Bytes");
+ setBytesMethodBuilder = getMethodOrDie(builderClass,
+ "set" + camelCaseName + "Bytes", ByteString.class);
+ }
+
+ private final Method getBytesMethod;
+ private final Method getBytesMethodBuilder;
+ private final Method setBytesMethodBuilder;
+
+ @Override
+ public Object getRaw(final GeneratedMessageV3 message) {
+ return invokeOrDie(getBytesMethod, message);
+ }
+
+ @Override
+ public Object getRaw(GeneratedMessageV3.Builder builder) {
+ return invokeOrDie(getBytesMethodBuilder, builder);
+ }
+
+ @Override
+ public void set(GeneratedMessageV3.Builder builder, Object value) {
+ if (value instanceof ByteString) {
+ invokeOrDie(setBytesMethodBuilder, builder, value);
+ } else {
+ super.set(builder, value);
+ }
+ }
+ }
+
+ // ---------------------------------------------------------------
+
+ private static final class SingularMessageFieldAccessor
+ extends SingularFieldAccessor {
+ SingularMessageFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass,
+ final String containingOneofCamelCaseName) {
+ super(descriptor, camelCaseName, messageClass, builderClass,
+ containingOneofCamelCaseName);
+
+ newBuilderMethod = getMethodOrDie(type, "newBuilder");
+ getBuilderMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Builder");
+ }
+
+ private final Method newBuilderMethod;
+ private final Method getBuilderMethodBuilder;
+
+ private Object coerceType(final Object value) {
+ if (type.isInstance(value)) {
+ return value;
+ } else {
+ // The value is not the exact right message type. However, if it
+ // is an alternative implementation of the same type -- e.g. a
+ // DynamicMessage -- we should accept it. In this case we can make
+ // a copy of the message.
+ return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
+ .mergeFrom((Message) value).buildPartial();
+ }
+ }
+
+ @Override
+ public void set(final Builder builder, final Object value) {
+ super.set(builder, coerceType(value));
+ }
+ @Override
+ public Message.Builder newBuilder() {
+ return (Message.Builder) invokeOrDie(newBuilderMethod, null);
+ }
+ @Override
+ public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) {
+ return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder);
+ }
+ }
+
+ private static final class RepeatedMessageFieldAccessor
+ extends RepeatedFieldAccessor {
+ RepeatedMessageFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass) {
+ super(descriptor, camelCaseName, messageClass, builderClass);
+
+ newBuilderMethod = getMethodOrDie(type, "newBuilder");
+ getBuilderMethodBuilder = getMethodOrDie(builderClass,
+ "get" + camelCaseName + "Builder", Integer.TYPE);
+ }
+
+ private final Method newBuilderMethod;
+ private final Method getBuilderMethodBuilder;
+
+ private Object coerceType(final Object value) {
+ if (type.isInstance(value)) {
+ return value;
+ } else {
+ // The value is not the exact right message type. However, if it
+ // is an alternative implementation of the same type -- e.g. a
+ // DynamicMessage -- we should accept it. In this case we can make
+ // a copy of the message.
+ return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
+ .mergeFrom((Message) value).build();
+ }
+ }
+
+ @Override
+ public void setRepeated(final Builder builder,
+ final int index, final Object value) {
+ super.setRepeated(builder, index, coerceType(value));
+ }
+ @Override
+ public void addRepeated(final Builder builder, final Object value) {
+ super.addRepeated(builder, coerceType(value));
+ }
+ @Override
+ public Message.Builder newBuilder() {
+ return (Message.Builder) invokeOrDie(newBuilderMethod, null);
+ }
+ @Override
+ public Message.Builder getRepeatedBuilder(
+ final GeneratedMessageV3.Builder builder, final int index) {
+ return (Message.Builder) invokeOrDie(
+ getBuilderMethodBuilder, builder, index);
+ }
+ }
+ }
+
+ /**
+ * Replaces this object in the output stream with a serialized form.
+ * Part of Java's serialization magic. Generated sub-classes must override
+ * this method by calling {@code return super.writeReplace();}
+ * @return a SerializedForm of this message
+ */
+ protected Object writeReplace() throws ObjectStreamException {
+ return new GeneratedMessageLite.SerializedForm(this);
+ }
+
+ /**
+ * Checks that the {@link Extension} is non-Lite and returns it as a
+ * {@link GeneratedExtension}.
+ */
+ private static <MessageType extends ExtendableMessage<MessageType>, T>
+ Extension<MessageType, T> checkNotLite(
+ ExtensionLite<MessageType, T> extension) {
+ if (extension.isLite()) {
+ throw new IllegalArgumentException("Expected non-lite extension.");
+ }
+
+ 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/core/src/main/java/com/google/protobuf/Internal.java b/java/core/src/main/java/com/google/protobuf/Internal.java
index d1de375e..3b4a0412 100644
--- a/java/core/src/main/java/com/google/protobuf/Internal.java
+++ b/java/core/src/main/java/com/google/protobuf/Internal.java
@@ -611,12 +611,12 @@ public final 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);
@@ -639,12 +639,12 @@ public final 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);
@@ -667,12 +667,12 @@ public final 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);
@@ -695,12 +695,12 @@ public final 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);
@@ -723,12 +723,12 @@ public final 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/core/src/main/java/com/google/protobuf/Parser.java b/java/core/src/main/java/com/google/protobuf/Parser.java
index 6db69247..cfbcb442 100644
--- a/java/core/src/main/java/com/google/protobuf/Parser.java
+++ b/java/core/src/main/java/com/google/protobuf/Parser.java
@@ -39,7 +39,7 @@ import java.io.InputStream;
*
* <p>All methods may throw {@link InvalidProtocolBufferException}. In the event of invalid data,
* like an encoding error, the cause of the thrown exception will be {@code null}. However, if an
- * I/O problem occurs, an exception is thrown with an {@link IOException} cause.
+ * I/O problem occurs, an exception is thrown with an {@link java.io.IOException} cause.
*
* @author liujisi@google.com (Pherl Liu)
*/
diff --git a/java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java b/java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java
index 2ecf912e..5c43b2c3 100644
--- a/java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java
+++ b/java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java
@@ -45,7 +45,7 @@ import java.util.Map.Entry;
*
* <p>The locations of primary fields values are retrieved by {@code getLocation} or
* {@code getLocations}. The locations of sub message values are within nested
- * {@code TextFormatParseInfoTree}s and are retrieve by {@getNestedTree} or {code @getNestedTrees}.
+ * {@code TextFormatParseInfoTree}s and are retrieve by {@code getNestedTree} or {@code getNestedTrees}.
*
* <p>The {@code TextFormatParseInfoTree} is created by a Builder.
*/
@@ -197,7 +197,7 @@ public class TextFormatParseInfoTree {
* Set for a sub message.
*
* <p>A new builder is created for a sub message. The builder that is returned is a new builder.
- * The return is <emph>not</emph> the invoked {@code builder.getBuilderForSubMessageField}.
+ * The return is <em>not</em> the invoked {@code builder.getBuilderForSubMessageField}.
*
* @param fieldDescriptor the field whose value is the submessage
* @return a new Builder for the sub message
diff --git a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
index 82f4216b..4a42c897 100644
--- a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
+++ b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
@@ -31,6 +31,8 @@
package com.google.protobuf;
import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
import com.google.protobuf.FieldPresenceTestProto.TestOptionalFieldsOnly;
@@ -253,6 +255,54 @@ public class FieldPresenceTest extends TestCase {
assertEquals(4, message.getAllFields().size());
}
+ public void testFieldPresenceDynamicMessage() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor optionalInt32Field = descriptor.findFieldByName("optional_int32");
+ FieldDescriptor optionalStringField = descriptor.findFieldByName("optional_string");
+ FieldDescriptor optionalBytesField = descriptor.findFieldByName("optional_bytes");
+ FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum");
+ EnumDescriptor enumDescriptor = optionalNestedEnumField.getEnumType();
+ EnumValueDescriptor defaultEnumValueDescriptor = enumDescriptor.getValues().get(0);
+ EnumValueDescriptor nonDefaultEnumValueDescriptor = enumDescriptor.getValues().get(1);
+
+ DynamicMessage defaultInstance = DynamicMessage.getDefaultInstance(descriptor);
+ // Field not present.
+ DynamicMessage message = defaultInstance.newBuilderForType().build();
+ assertFalse(message.hasField(optionalInt32Field));
+ assertFalse(message.hasField(optionalStringField));
+ assertFalse(message.hasField(optionalBytesField));
+ assertFalse(message.hasField(optionalNestedEnumField));
+ assertEquals(0, message.getAllFields().size());
+
+ // Field set to non-default value is seen as present.
+ message =
+ defaultInstance
+ .newBuilderForType()
+ .setField(optionalInt32Field, 1)
+ .setField(optionalStringField, "x")
+ .setField(optionalBytesField, ByteString.copyFromUtf8("y"))
+ .setField(optionalNestedEnumField, nonDefaultEnumValueDescriptor)
+ .build();
+ assertTrue(message.hasField(optionalInt32Field));
+ assertTrue(message.hasField(optionalStringField));
+ assertTrue(message.hasField(optionalBytesField));
+ assertTrue(message.hasField(optionalNestedEnumField));
+ assertEquals(4, message.getAllFields().size());
+
+ // Field set to default value is seen as not present.
+ message = message.toBuilder()
+ .setField(optionalInt32Field, 0)
+ .setField(optionalStringField, "")
+ .setField(optionalBytesField, ByteString.EMPTY)
+ .setField(optionalNestedEnumField, defaultEnumValueDescriptor)
+ .build();
+ assertFalse(message.hasField(optionalInt32Field));
+ assertFalse(message.hasField(optionalStringField));
+ assertFalse(message.hasField(optionalBytesField));
+ assertFalse(message.hasField(optionalNestedEnumField));
+ assertEquals(0, message.getAllFields().size());
+ }
+
public void testMessageField() {
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
assertFalse(builder.hasOptionalNestedMessage());
diff --git a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index a9b8b638..127e06fd 100644
--- a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -972,7 +972,7 @@ public class GeneratedMessageTest extends TestCase {
TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
TestAllTypes.Builder builder = (TestAllTypes.Builder)
- ((GeneratedMessage) TestAllTypes.getDefaultInstance()).
+ ((AbstractMessage) TestAllTypes.getDefaultInstance()).
newBuilderForType(mockParent);
builder.setOptionalInt32(1);
builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR);
@@ -1027,7 +1027,7 @@ public class GeneratedMessageTest extends TestCase {
TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
TestAllExtensions.Builder builder = (TestAllExtensions.Builder)
- ((GeneratedMessage) TestAllExtensions.getDefaultInstance()).
+ ((AbstractMessage) TestAllExtensions.getDefaultInstance()).
newBuilderForType(mockParent);
builder.addExtension(UnittestProto.repeatedInt32Extension, 1);
diff --git a/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java b/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
index 0f42ac50..497c4df2 100644
--- a/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
+++ b/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
@@ -35,6 +35,7 @@ import static java.util.Arrays.asList;
import junit.framework.TestCase;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
@@ -233,7 +234,7 @@ public class LazyStringArrayListTest extends TestCase {
}
try {
- list.addAllByteArray(asList(BYTE_STRING_A.toByteArray()));
+ list.addAllByteArray(Collections.singletonList(BYTE_STRING_A.toByteArray()));
fail();
} catch (UnsupportedOperationException e) {
// expected
diff --git a/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java b/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java
deleted file mode 100644
index 49d52321..00000000
--- a/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java
+++ /dev/null
@@ -1,190 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf;
-
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
-
-import junit.framework.TestCase;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Tests for {@link RepeatedFieldBuilder}. This tests basic functionality.
- * More extensive testing is provided via other tests that exercise the
- * builder.
- *
- * @author jonp@google.com (Jon Perlow)
- */
-public class RepeatedFieldBuilderTest extends TestCase {
-
- public void testBasicUse() {
- TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
- RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
- builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
- builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
- assertEquals(0, builder.getMessage(0).getOptionalInt32());
- assertEquals(1, builder.getMessage(1).getOptionalInt32());
-
- List<TestAllTypes> list = builder.build();
- assertEquals(2, list.size());
- assertEquals(0, list.get(0).getOptionalInt32());
- assertEquals(1, list.get(1).getOptionalInt32());
- assertIsUnmodifiable(list);
-
- // Make sure it doesn't change.
- List<TestAllTypes> list2 = builder.build();
- assertSame(list, list2);
- assertEquals(0, mockParent.getInvalidationCount());
- }
-
- public void testGoingBackAndForth() {
- TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
- RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
- builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
- builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
- assertEquals(0, builder.getMessage(0).getOptionalInt32());
- assertEquals(1, builder.getMessage(1).getOptionalInt32());
-
- // Convert to list
- List<TestAllTypes> list = builder.build();
- assertEquals(2, list.size());
- assertEquals(0, list.get(0).getOptionalInt32());
- assertEquals(1, list.get(1).getOptionalInt32());
- assertIsUnmodifiable(list);
-
- // Update 0th item
- assertEquals(0, mockParent.getInvalidationCount());
- builder.getBuilder(0).setOptionalString("foo");
- assertEquals(1, mockParent.getInvalidationCount());
- list = builder.build();
- assertEquals(2, list.size());
- assertEquals(0, list.get(0).getOptionalInt32());
- assertEquals("foo", list.get(0).getOptionalString());
- assertEquals(1, list.get(1).getOptionalInt32());
- assertIsUnmodifiable(list);
- assertEquals(1, mockParent.getInvalidationCount());
- }
-
- public void testVariousMethods() {
- TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
- RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
- builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
- builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(2).build());
- builder.addBuilder(0, TestAllTypes.getDefaultInstance())
- .setOptionalInt32(0);
- builder.addBuilder(TestAllTypes.getDefaultInstance()).setOptionalInt32(3);
-
- assertEquals(0, builder.getMessage(0).getOptionalInt32());
- assertEquals(1, builder.getMessage(1).getOptionalInt32());
- assertEquals(2, builder.getMessage(2).getOptionalInt32());
- assertEquals(3, builder.getMessage(3).getOptionalInt32());
-
- assertEquals(0, mockParent.getInvalidationCount());
- List<TestAllTypes> messages = builder.build();
- assertEquals(4, messages.size());
- assertSame(messages, builder.build()); // expect same list
-
- // Remove a message.
- builder.remove(2);
- assertEquals(1, mockParent.getInvalidationCount());
- assertEquals(3, builder.getCount());
- assertEquals(0, builder.getMessage(0).getOptionalInt32());
- assertEquals(1, builder.getMessage(1).getOptionalInt32());
- assertEquals(3, builder.getMessage(2).getOptionalInt32());
-
- // Remove a builder.
- builder.remove(0);
- assertEquals(1, mockParent.getInvalidationCount());
- assertEquals(2, builder.getCount());
- assertEquals(1, builder.getMessage(0).getOptionalInt32());
- assertEquals(3, builder.getMessage(1).getOptionalInt32());
-
- // Test clear.
- builder.clear();
- assertEquals(1, mockParent.getInvalidationCount());
- assertEquals(0, builder.getCount());
- assertTrue(builder.isEmpty());
- }
-
- public void testLists() {
- TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
- RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
- builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
- builder.addMessage(0,
- TestAllTypes.newBuilder().setOptionalInt32(0).build());
- assertEquals(0, builder.getMessage(0).getOptionalInt32());
- assertEquals(1, builder.getMessage(1).getOptionalInt32());
-
- // Use list of builders.
- List<TestAllTypes.Builder> builders = builder.getBuilderList();
- assertEquals(0, builders.get(0).getOptionalInt32());
- assertEquals(1, builders.get(1).getOptionalInt32());
- builders.get(0).setOptionalInt32(10);
- builders.get(1).setOptionalInt32(11);
-
- // Use list of protos
- List<TestAllTypes> protos = builder.getMessageList();
- assertEquals(10, protos.get(0).getOptionalInt32());
- assertEquals(11, protos.get(1).getOptionalInt32());
-
- // Add an item to the builders and verify it's updated in both
- builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(12).build());
- assertEquals(3, builders.size());
- assertEquals(3, protos.size());
- }
-
- private void assertIsUnmodifiable(List<?> list) {
- if (list == Collections.emptyList()) {
- // OKAY -- Need to check this b/c EmptyList allows you to call clear.
- } else {
- try {
- list.clear();
- fail("List wasn't immutable");
- } catch (UnsupportedOperationException e) {
- // good
- }
- }
- }
-
- private RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder>
- newRepeatedFieldBuilder(GeneratedMessage.BuilderParent parent) {
- return new RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder>(Collections.<TestAllTypes>emptyList(), false,
- parent, false);
- }
-}
diff --git a/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java b/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java
deleted file mode 100644
index 58b80007..00000000
--- a/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java
+++ /dev/null
@@ -1,155 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf;
-
-import protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
-
-import junit.framework.TestCase;
-
-/**
- * Tests for {@link SingleFieldBuilder}. This tests basic functionality.
- * More extensive testing is provided via other tests that exercise the
- * builder.
- *
- * @author jonp@google.com (Jon Perlow)
- */
-public class SingleFieldBuilderTest extends TestCase {
-
- public void testBasicUseAndInvalidations() {
- TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
- SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder> builder =
- new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder>(
- TestAllTypes.getDefaultInstance(),
- mockParent,
- false);
- assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
- assertEquals(TestAllTypes.getDefaultInstance(),
- builder.getBuilder().buildPartial());
- assertEquals(0, mockParent.getInvalidationCount());
-
- builder.getBuilder().setOptionalInt32(10);
- assertEquals(0, mockParent.getInvalidationCount());
- TestAllTypes message = builder.build();
- assertEquals(10, message.getOptionalInt32());
-
- // Test that we receive invalidations now that build has been called.
- assertEquals(0, mockParent.getInvalidationCount());
- builder.getBuilder().setOptionalInt32(20);
- assertEquals(1, mockParent.getInvalidationCount());
-
- // Test that we don't keep getting invalidations on every change
- builder.getBuilder().setOptionalInt32(30);
- assertEquals(1, mockParent.getInvalidationCount());
-
- }
-
- public void testSetMessage() {
- TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
- SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder> builder =
- new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder>(
- TestAllTypes.getDefaultInstance(),
- mockParent,
- false);
- builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
- assertEquals(0, builder.getMessage().getOptionalInt32());
-
- // Update message using the builder
- builder.getBuilder().setOptionalInt32(1);
- assertEquals(0, mockParent.getInvalidationCount());
- assertEquals(1, builder.getBuilder().getOptionalInt32());
- assertEquals(1, builder.getMessage().getOptionalInt32());
- builder.build();
- builder.getBuilder().setOptionalInt32(2);
- assertEquals(2, builder.getBuilder().getOptionalInt32());
- assertEquals(2, builder.getMessage().getOptionalInt32());
-
- // Make sure message stays cached
- assertSame(builder.getMessage(), builder.getMessage());
- }
-
- public void testClear() {
- TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
- SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder> builder =
- new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder>(
- TestAllTypes.getDefaultInstance(),
- mockParent,
- false);
- builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
- assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
- builder.clear();
- assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
-
- builder.getBuilder().setOptionalInt32(1);
- assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
- builder.clear();
- assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
- }
-
- public void testMerge() {
- TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
- SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder> builder =
- new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
- TestAllTypesOrBuilder>(
- TestAllTypes.getDefaultInstance(),
- mockParent,
- false);
-
- // Merge into default field.
- builder.mergeFrom(TestAllTypes.getDefaultInstance());
- assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
-
- // Merge into non-default field on existing builder.
- builder.getBuilder().setOptionalInt32(2);
- builder.mergeFrom(TestAllTypes.newBuilder()
- .setOptionalDouble(4.0)
- .buildPartial());
- assertEquals(2, builder.getMessage().getOptionalInt32());
- assertEquals(4.0, builder.getMessage().getOptionalDouble());
-
- // Merge into non-default field on existing message
- builder.setMessage(TestAllTypes.newBuilder()
- .setOptionalInt32(10)
- .buildPartial());
- builder.mergeFrom(TestAllTypes.newBuilder()
- .setOptionalDouble(5.0)
- .buildPartial());
- assertEquals(10, builder.getMessage().getOptionalInt32());
- assertEquals(5.0, builder.getMessage().getOptionalDouble());
- }
-}
diff --git a/java/lite/pom.xml b/java/lite/pom.xml
index c403dc09..9862cd94 100644
--- a/java/lite/pom.xml
+++ b/java/lite/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
- <version>3.0.0-beta-3</version>
+ <version>3.0.0</version>
</parent>
<artifactId>protobuf-lite</artifactId>
diff --git a/java/pom.xml b/java/pom.xml
index 7a1a91f8..3a91a0ba 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -11,7 +11,7 @@
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
- <version>3.0.0-beta-3</version>
+ <version>3.0.0</version>
<packaging>pom</packaging>
<name>Protocol Buffers [Parent]</name>
@@ -152,6 +152,32 @@
<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>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
@@ -182,7 +208,7 @@
<modules>
<module>core</module>
- <module>lite</module>
+ <!-- <module>lite</module> -->
<module>util</module>
</modules>
diff --git a/java/util/pom.xml b/java/util/pom.xml
index 9236f907..0d5e8e37 100644
--- a/java/util/pom.xml
+++ b/java/util/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
- <version>3.0.0-beta-3</version>
+ <version>3.0.0</version>
</parent>
<artifactId>protobuf-java-util</artifactId>
diff --git a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
index 297545e5..d4db9c80 100644
--- a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
+++ b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
@@ -116,7 +116,8 @@ public class JsonFormat {
private Printer(
TypeRegistry registry,
boolean includingDefaultValueFields,
- boolean preservingProtoFieldNames, boolean omittingInsignificantWhitespace) {
+ boolean preservingProtoFieldNames,
+ boolean omittingInsignificantWhitespace) {
this.registry = registry;
this.includingDefaultValueFields = includingDefaultValueFields;
this.preservingProtoFieldNames = preservingProtoFieldNames;
@@ -133,7 +134,11 @@ public class JsonFormat {
if (this.registry != TypeRegistry.getEmptyTypeRegistry()) {
throw new IllegalArgumentException("Only one registry is allowed.");
}
- return new Printer(registry, includingDefaultValueFields, preservingProtoFieldNames, omittingInsignificantWhitespace);
+ return new Printer(
+ registry,
+ includingDefaultValueFields,
+ preservingProtoFieldNames,
+ omittingInsignificantWhitespace);
}
/**
@@ -143,7 +148,8 @@ public class JsonFormat {
* {@link Printer}.
*/
public Printer includingDefaultValueFields() {
- return new Printer(registry, true, preservingProtoFieldNames, omittingInsignificantWhitespace);
+ return new Printer(
+ registry, true, preservingProtoFieldNames, omittingInsignificantWhitespace);
}
/**
@@ -153,7 +159,8 @@ public class JsonFormat {
* current {@link Printer}.
*/
public Printer preservingProtoFieldNames() {
- return new Printer(registry, includingDefaultValueFields, true, omittingInsignificantWhitespace);
+ return new Printer(
+ registry, includingDefaultValueFields, true, omittingInsignificantWhitespace);
}
@@ -172,7 +179,7 @@ public class JsonFormat {
* See <a href="https://tools.ietf.org/html/rfc7159">https://tools.ietf.org/html/rfc7159</a>
* current {@link Printer}.
*/
- public Printer omittingInsignificantWhitespace(){
+ public Printer omittingInsignificantWhitespace() {
return new Printer(registry, includingDefaultValueFields, preservingProtoFieldNames, true);
}
@@ -186,7 +193,12 @@ public class JsonFormat {
public void appendTo(MessageOrBuilder message, Appendable output) throws IOException {
// TODO(xiaofeng): Investigate the allocation overhead and optimize for
// mobile.
- new PrinterImpl(registry, includingDefaultValueFields, preservingProtoFieldNames, output, omittingInsignificantWhitespace)
+ new PrinterImpl(
+ registry,
+ includingDefaultValueFields,
+ preservingProtoFieldNames,
+ output,
+ omittingInsignificantWhitespace)
.print(message);
}
@@ -212,7 +224,7 @@ public class JsonFormat {
* Creates a {@link Parser} with default configuration.
*/
public static Parser parser() {
- return new Parser(TypeRegistry.getEmptyTypeRegistry());
+ return new Parser(TypeRegistry.getEmptyTypeRegistry(), false);
}
/**
@@ -220,9 +232,11 @@ public class JsonFormat {
*/
public static class Parser {
private final TypeRegistry registry;
+ private final boolean ignoringUnknownFields;
- private Parser(TypeRegistry registry) {
+ private Parser(TypeRegistry registry, boolean ignoreUnknownFields) {
this.registry = registry;
+ this.ignoringUnknownFields = ignoreUnknownFields;
}
/**
@@ -235,7 +249,16 @@ public class JsonFormat {
if (this.registry != TypeRegistry.getEmptyTypeRegistry()) {
throw new IllegalArgumentException("Only one registry is allowed.");
}
- return new Parser(registry);
+ return new Parser(registry, this.ignoringUnknownFields);
+ }
+
+ /**
+ * Creates a new {@link Parser} configured to not throw an exception
+ * when an unknown field is encountered. The new Parser clones all other
+ * configurations from this Parser.
+ */
+ public Parser ignoringUnknownFields() {
+ return new Parser(this.registry, true);
}
/**
@@ -247,7 +270,7 @@ public class JsonFormat {
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);
+ new ParserImpl(registry, ignoringUnknownFields).merge(json, builder);
}
/**
@@ -260,7 +283,7 @@ public class JsonFormat {
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);
+ new ParserImpl(registry, ignoringUnknownFields).merge(json, builder);
}
}
@@ -379,18 +402,18 @@ public class JsonFormat {
*/
interface TextGenerator {
void indent();
+
void outdent();
+
void print(final CharSequence text) throws IOException;
}
-
/**
* Format the json without indentation
*/
- private static final class CompactTextGenerator implements TextGenerator{
+ private static final class CompactTextGenerator implements TextGenerator {
private final Appendable output;
-
private CompactTextGenerator(final Appendable output) {
this.output = output;
}
@@ -411,12 +434,11 @@ public class JsonFormat {
public void print(final CharSequence text) throws IOException {
output.append(text);
}
-
}
/**
* A TextGenerator adds indentation when writing formatted text.
*/
- private static final class PrettyTextGenerator implements TextGenerator{
+ private static final class PrettyTextGenerator implements TextGenerator {
private final Appendable output;
private final StringBuilder indent = new StringBuilder();
private boolean atStartOfLine = true;
@@ -496,7 +518,8 @@ public class JsonFormat {
TypeRegistry registry,
boolean includingDefaultValueFields,
boolean preservingProtoFieldNames,
- Appendable jsonOutput, boolean omittingInsignificantWhitespace) {
+ Appendable jsonOutput,
+ boolean omittingInsignificantWhitespace) {
this.registry = registry;
this.includingDefaultValueFields = includingDefaultValueFields;
this.preservingProtoFieldNames = preservingProtoFieldNames;
@@ -734,9 +757,7 @@ public class JsonFormat {
}
/** Prints a regular message with an optional type URL. */
-
- private void print(MessageOrBuilder message, String typeUrl)
- throws IOException {
+ private void print(MessageOrBuilder message, String typeUrl) throws IOException {
generator.print("{" + blankOrNewLine);
generator.indent();
@@ -1014,9 +1035,11 @@ public class JsonFormat {
private static class ParserImpl {
private final TypeRegistry registry;
private final JsonParser jsonParser;
+ private final boolean ignoringUnknownFields;
- ParserImpl(TypeRegistry registry) {
+ ParserImpl(TypeRegistry registry, boolean ignoreUnknownFields) {
this.registry = registry;
+ this.ignoringUnknownFields = ignoreUnknownFields;
this.jsonParser = new JsonParser();
}
@@ -1181,6 +1204,9 @@ public class JsonFormat {
}
FieldDescriptor field = fieldNameMap.get(entry.getKey());
if (field == null) {
+ if (ignoringUnknownFields) {
+ continue;
+ }
throw new InvalidProtocolBufferException(
"Cannot find field: "
+ entry.getKey()
diff --git a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
index e68c7be1..c11114c0 100644
--- a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
+++ b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
@@ -140,7 +140,7 @@ public class JsonFormatTest extends TestCase {
private String toJsonString(Message message) throws IOException {
return JsonFormat.printer().print(message);
}
- private String toCompactJsonString(Message message) throws IOException{
+ private String toCompactJsonString(Message message) throws IOException {
return JsonFormat.printer().omittingInsignificantWhitespace().print(message);
}
@@ -1030,6 +1030,22 @@ public class JsonFormatTest extends TestCase {
}
}
+ public void testParserUnknownFields() throws Exception {
+ try {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ String json = "{\n" + " \"unknownField\": \"XXX\"\n" + "}";
+ JsonFormat.parser().merge(json, builder);
+ fail("Exception is expected.");
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+ public void testParserIgnoringUnknownFields() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ String json = "{\n" + " \"unknownField\": \"XXX\"\n" + "}";
+ JsonFormat.parser().ignoringUnknownFields().merge(json, builder);
+ }
+
public void testCustomJsonName() throws Exception {
TestCustomJsonName message = TestCustomJsonName.newBuilder().setValue(12345).build();
assertEquals("{\n" + " \"@value\": 12345\n" + "}", JsonFormat.printer().print(message));
@@ -1172,7 +1188,9 @@ public class JsonFormatTest extends TestCase {
public void testOmittingInsignificantWhiteSpace() throws Exception {
TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(12345).build();
- assertEquals("{" + "\"optionalInt32\":12345" + "}", JsonFormat.printer().omittingInsignificantWhitespace().print(message));
+ assertEquals(
+ "{" + "\"optionalInt32\":12345" + "}",
+ JsonFormat.printer().omittingInsignificantWhitespace().print(message));
TestAllTypes message1 = TestAllTypes.getDefaultInstance();
assertEquals("{}", JsonFormat.printer().omittingInsignificantWhitespace().print(message1));
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
@@ -1224,4 +1242,20 @@ public class JsonFormatTest extends TestCase {
toCompactJsonString(message2));
}
+ // Regression test for b/29892357
+ public void testEmptyWrapperTypesInAny() throws Exception {
+ JsonFormat.TypeRegistry registry =
+ JsonFormat.TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build();
+ JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(registry);
+
+ Any.Builder builder = Any.newBuilder();
+ parser.merge(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.BoolValue\",\n"
+ + " \"value\": false\n"
+ + "}\n",
+ builder);
+ Any any = builder.build();
+ assertEquals(0, any.getValue().size());
+ }
}
diff --git a/javanano/pom.xml b/javanano/pom.xml
index a2eca09d..6ebba3cf 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-6</version>
+ <version>3.0.0-alpha-7</version>
<packaging>bundle</packaging>
<name>Protocol Buffer JavaNano API</name>
<description>
@@ -164,8 +164,8 @@
<configuration>
<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-5</Export-Package>
+ <Bundle-SymbolicName>com.google.protobuf.nano</Bundle-SymbolicName>
+ <Export-Package>com.google.protobuf.nano;version=3.0.0-alpha-7</Export-Package>
</instructions>
</configuration>
</plugin>
diff --git a/jenkins/docker/Dockerfile b/jenkins/docker/Dockerfile
index 8467aeff..53ac38f3 100644
--- a/jenkins/docker/Dockerfile
+++ b/jenkins/docker/Dockerfile
@@ -23,6 +23,13 @@ run echo "deb http://download.mono-project.com/repo/debian wheezy main" | tee /e
echo "deb http://download.mono-project.com/repo/debian wheezy-libjpeg62-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list && \
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
+# Install dotnet SDK based on https://www.microsoft.com/net/core#debian
+# (Ubuntu instructions need apt to support https)
+RUN apt-get update && apt-get install -y curl libunwind8 gettext && \
+ curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?LinkID=809130 && \
+ mkdir -p /opt/dotnet && tar zxf dotnet.tar.gz -C /opt/dotnet && \
+ ln -s /opt/dotnet/dotnet /usr/local/bin
+
# Install dependencies. We start with the basic ones require to build protoc
# and the C++ build
RUN apt-get update && apt-get install -y \
@@ -80,7 +87,6 @@ RUN wget www.nuget.org/NuGet.exe -O /usr/local/bin/nuget.exe
RUN pip install pip --upgrade
RUN pip install virtualenv tox yattag
-
##################
# Ruby dependencies
@@ -88,12 +94,12 @@ RUN pip install virtualenv tox yattag
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
RUN \curl -sSL https://get.rvm.io | bash -s stable
-# Install Ruby 2.1
+# Install Ruby 2.1, Ruby 2.2 and JRuby 1.7
RUN /bin/bash -l -c "rvm install ruby-2.1"
-RUN /bin/bash -l -c "rvm use --default ruby-2.1"
+RUN /bin/bash -l -c "rvm install ruby-2.2"
+RUN /bin/bash -l -c "rvm install jruby-1.7"
RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
-RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc"
##################
@@ -111,12 +117,29 @@ RUN cd /tmp && \
./configure && \
make -j6 && \
cd java && \
- $MVN install dependency:go-offline -Dmaven.repo.local=$MAVEN_REPO -P lite && \
$MVN install dependency:go-offline -Dmaven.repo.local=$MAVEN_REPO && \
cd ../javanano && \
$MVN install dependency:go-offline -Dmaven.repo.local=$MAVEN_REPO
##################
+# Go dependencies.
+RUN apt-get install -y \
+ # -- For go -- \
+ golang
+
+##################
+# Javascript dependencies.
+Run apt-get install -y \
+ # -- For javascript -- \
+ npm
+
+# On Debian/Ubuntu, nodejs binary is named 'nodejs' because the name 'node'
+# is taken by another legacy binary. We don't have that legacy binary and
+# npm expects the binary to be named 'node', so we just create a symbol
+# link here.
+RUN ln -s `which nodejs` /usr/bin/node
+
+##################
# Prepare ccache
RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
diff --git a/jenkins/pull_request_in_docker.sh b/jenkins/pull_request_in_docker.sh
index 887f97c5..78a9253a 100755
--- a/jenkins/pull_request_in_docker.sh
+++ b/jenkins/pull_request_in_docker.sh
@@ -55,7 +55,9 @@ parallel --results $LOG_OUTPUT_DIR --joblog $OUTPUT_DIR/joblog $TEST_SCRIPT :::
javanano_oracle7 \
python \
python_cpp \
- ruby21 \
+ ruby_all \
+ javascript \
+ golang \
|| true # Process test results even if tests fail.
cat $OUTPUT_DIR/joblog
diff --git a/js/README.md b/js/README.md
index 15d48c87..f4184621 100644
--- a/js/README.md
+++ b/js/README.md
@@ -152,8 +152,7 @@ idea of how the library generally works:
// Serializes to a UInt8Array.
bytes = message.serializeBinary();
- var message2 = new MyMessage();
- message2.deserializeBinary(bytes);
+ var message2 = MyMessage.deserializeBinary(bytes);
For more examples, see the tests. You can also look at the generated code
to see what methods are defined for your generated messages.
diff --git a/js/commonjs/export.js b/js/commonjs/export.js
index a3cfbd6f..2403b1a4 100644
--- a/js/commonjs/export.js
+++ b/js/commonjs/export.js
@@ -8,13 +8,17 @@
goog.require('goog.object');
goog.require('jspb.BinaryReader');
goog.require('jspb.BinaryWriter');
+goog.require('jspb.ExtensionFieldBinaryInfo');
goog.require('jspb.ExtensionFieldInfo');
goog.require('jspb.Message');
+goog.require('jspb.Map');
+exports.Map = jspb.Map;
exports.Message = jspb.Message;
exports.BinaryReader = jspb.BinaryReader;
exports.BinaryWriter = jspb.BinaryWriter;
exports.ExtensionFieldInfo = jspb.ExtensionFieldInfo;
+exports.ExtensionFieldBinaryInfo = jspb.ExtensionFieldBinaryInfo;
// These are used by generated code but should not be used directly by clients.
exports.exportSymbol = goog.exportSymbol;
diff --git a/js/debug.js b/js/debug.js
index 3701a095..3c1ada02 100644
--- a/js/debug.js
+++ b/js/debug.js
@@ -94,8 +94,10 @@ jspb.debug.dump_ = function(thing) {
var match = /^get([A-Z]\w*)/.exec(name);
if (match && name != 'getExtension' &&
name != 'getJsPbMessageId') {
- var val = thing[name]();
- if (val != null) {
+ var has = 'has' + match[1];
+ if (!thing[has] || thing[has]())
+ {
+ var val = thing[name]();
object[jspb.debug.formatFieldName_(match[1])] = jspb.debug.dump_(val);
}
}
diff --git a/js/map.js b/js/map.js
index 821765ec..e6406a60 100644
--- a/js/map.js
+++ b/js/map.js
@@ -44,65 +44,23 @@ goog.forwardDeclare('jspb.BinaryWriter');
* on ES6 itself.
*
* This constructor should only be called from generated message code. It is not
- * intended for general use by library consumers. The callback function
- * arguments are references to methods in `BinaryReader` and `BinaryWriter`, as
- * well as constructors and reader/writer methods in submessage types if
- * appropriate, that are used for binary serialization and parsing.
+ * intended for general use by library consumers.
*
* @template K, V
*
* @param {!Array<!Array<!Object>>} arr
*
- * @param {function(this:jspb.BinaryWriter,number,K)=} opt_keyWriterFn
- * The method on BinaryWriter that writes type K to the stream.
- *
- * @param {function(this:jspb.BinaryReader):K=} opt_keyReaderFn
- * The method on BinaryReader that reads type K from the stream.
- *
- * @param {function(this:jspb.BinaryWriter,number,V)|
- * function(this:jspb.BinaryReader,V,?)=} opt_valueWriterFn
- * The method on BinaryWriter that writes type V to the stream. May be
- * writeMessage, in which case the second callback arg form is used.
- *
- * @param {function(this:jspb.BinaryReader):V|
- * function(this:jspb.BinaryReader,V,
- * function(V,!jspb.BinaryReader))=} opt_valueReaderFn
- * The method on BinaryReader that reads type V from the stream. May be
- * readMessage, in which case the second callback arg form is used.
- *
* @param {?function(new:V)|function(new:V,?)=} opt_valueCtor
* The constructor for type V, if type V is a message type.
*
- * @param {?function(V,!jspb.BinaryWriter)=} opt_valueWriterCallback
- * The BinaryWriter serialization callback for type V, if V is a message
- * type.
- *
- * @param {?function(V,!jspb.BinaryReader)=} opt_valueReaderCallback
- * The BinaryReader parsing callback for type V, if V is a message type.
- *
* @constructor
* @struct
*/
-jspb.Map = function(
- arr, opt_keyWriterFn, opt_keyReaderFn, opt_valueWriterFn, opt_valueReaderFn,
- opt_valueCtor, opt_valueWriterCallback, opt_valueReaderCallback) {
-
+jspb.Map = function(arr, opt_valueCtor) {
/** @const @private */
this.arr_ = arr;
/** @const @private */
- this.keyWriterFn_ = opt_keyWriterFn;
- /** @const @private */
- this.keyReaderFn_ = opt_keyReaderFn;
- /** @const @private */
- this.valueWriterFn_ = opt_valueWriterFn;
- /** @const @private */
- this.valueReaderFn_ = opt_valueReaderFn;
- /** @const @private */
this.valueCtor_ = opt_valueCtor;
- /** @const @private */
- this.valueWriterCallback_ = opt_valueWriterCallback;
- /** @const @private */
- this.valueReaderCallback_ = opt_valueReaderCallback;
/** @type {!Object<string, !jspb.Map.Entry_<K,V>>} @private */
this.map_ = {};
@@ -385,19 +343,29 @@ jspb.Map.prototype.has = function(key) {
* number.
* @param {number} fieldNumber
* @param {!jspb.BinaryWriter} writer
+ * @param {function(this:jspb.BinaryWriter,number,K)=} keyWriterFn
+ * The method on BinaryWriter that writes type K to the stream.
+ * @param {function(this:jspb.BinaryWriter,number,V)|
+ * function(this:jspb.BinaryReader,V,?)=} valueWriterFn
+ * The method on BinaryWriter that writes type V to the stream. May be
+ * writeMessage, in which case the second callback arg form is used.
+ * @param {?function(V,!jspb.BinaryWriter)=} opt_valueWriterCallback
+ * The BinaryWriter serialization callback for type V, if V is a message
+ * type.
*/
-jspb.Map.prototype.serializeBinary = function(fieldNumber, writer) {
+jspb.Map.prototype.serializeBinary = function(
+ fieldNumber, writer, keyWriterFn, valueWriterFn, opt_valueWriterCallback) {
var strKeys = this.stringKeys_();
strKeys.sort();
for (var i = 0; i < strKeys.length; i++) {
var entry = this.map_[strKeys[i]];
writer.beginSubMessage(fieldNumber);
- this.keyWriterFn_.call(writer, 1, entry.key);
+ keyWriterFn.call(writer, 1, entry.key);
if (this.valueCtor_) {
- this.valueWriterFn_.call(writer, 2, this.wrapEntry_(entry),
- this.valueWriterCallback_);
+ valueWriterFn.call(writer, 2, this.wrapEntry_(entry),
+ opt_valueWriterCallback);
} else {
- this.valueWriterFn_.call(writer, 2, entry.value);
+ valueWriterFn.call(writer, 2, entry.value);
}
writer.endSubMessage();
}
@@ -410,8 +378,21 @@ jspb.Map.prototype.serializeBinary = function(fieldNumber, writer) {
* when a key/value pair submessage is encountered.
* @param {!jspb.Map} map
* @param {!jspb.BinaryReader} reader
+ * @param {function(this:jspb.BinaryReader):K=} keyReaderFn
+ * The method on BinaryReader that reads type K from the stream.
+ *
+ * @param {function(this:jspb.BinaryReader):V|
+ * function(this:jspb.BinaryReader,V,
+ * function(V,!jspb.BinaryReader))=} valueReaderFn
+ * The method on BinaryReader that reads type V from the stream. May be
+ * readMessage, in which case the second callback arg form is used.
+ *
+ * @param {?function(V,!jspb.BinaryReader)=} opt_valueReaderCallback
+ * The BinaryReader parsing callback for type V, if V is a message type.
+ *
*/
-jspb.Map.deserializeBinary = function(map, reader) {
+jspb.Map.deserializeBinary = function(map, reader, keyReaderFn, valueReaderFn,
+ opt_valueReaderCallback) {
var key = undefined;
var value = undefined;
@@ -422,14 +403,14 @@ jspb.Map.deserializeBinary = function(map, reader) {
var field = reader.getFieldNumber();
if (field == 1) {
// Key.
- key = map.keyReaderFn_.call(reader);
+ key = keyReaderFn.call(reader);
} else if (field == 2) {
// Value.
if (map.valueCtor_) {
value = new map.valueCtor_();
- map.valueReaderFn_.call(reader, value, map.valueReaderCallback_);
+ valueReaderFn.call(reader, value, opt_valueReaderCallback);
} else {
- value = map.valueReaderFn_.call(reader);
+ value = valueReaderFn.call(reader);
}
}
}
diff --git a/js/message.js b/js/message.js
index 3863bac0..631ebe69 100644
--- a/js/message.js
+++ b/js/message.js
@@ -34,6 +34,7 @@
* @author mwr@google.com (Mark Rawling)
*/
+goog.provide('jspb.ExtensionFieldBinaryInfo');
goog.provide('jspb.ExtensionFieldInfo');
goog.provide('jspb.Message');
@@ -84,19 +85,12 @@ goog.forwardDeclare('xid.String');
* @param {?function(new: jspb.Message, Array=)} ctor
* @param {?function((boolean|undefined),!jspb.Message):!Object} toObjectFn
* @param {number} isRepeated
- * @param {?function(number,?)=} opt_binaryReaderFn
- * @param {?function(number,?)|function(number,?,?,?,?,?)=} opt_binaryWriterFn
- * @param {?function(?,?)=} opt_binaryMessageSerializeFn
- * @param {?function(?,?)=} opt_binaryMessageDeserializeFn
- * @param {?boolean=} opt_isPacked
* @constructor
* @struct
* @template T
*/
jspb.ExtensionFieldInfo = function(fieldNumber, fieldName, ctor, toObjectFn,
- isRepeated, opt_binaryReaderFn, opt_binaryWriterFn,
- opt_binaryMessageSerializeFn, opt_binaryMessageDeserializeFn,
- opt_isPacked) {
+ isRepeated) {
/** @const */
this.fieldIndex = fieldNumber;
/** @const */
@@ -106,20 +100,37 @@ jspb.ExtensionFieldInfo = function(fieldNumber, fieldName, ctor, toObjectFn,
/** @const */
this.toObjectFn = toObjectFn;
/** @const */
- this.binaryReaderFn = opt_binaryReaderFn;
+ this.isRepeated = isRepeated;
+};
+
+/**
+ * Stores binary-related information for a single extension field.
+ * @param {!jspb.ExtensionFieldInfo<T>} fieldInfo
+ * @param {?function(number,?)=} binaryReaderFn
+ * @param {?function(number,?)|function(number,?,?,?,?,?)=} binaryWriterFn
+ * @param {?function(?,?)=} opt_binaryMessageSerializeFn
+ * @param {?function(?,?)=} opt_binaryMessageDeserializeFn
+ * @param {?boolean=} opt_isPacked
+ * @constructor
+ * @struct
+ * @template T
+ */
+jspb.ExtensionFieldBinaryInfo = function(fieldInfo, binaryReaderFn, binaryWriterFn,
+ binaryMessageSerializeFn, binaryMessageDeserializeFn, isPacked) {
+ /** @const */
+ this.fieldInfo = fieldInfo;
/** @const */
- this.binaryWriterFn = opt_binaryWriterFn;
+ this.binaryReaderFn = binaryReaderFn;
/** @const */
- this.binaryMessageSerializeFn = opt_binaryMessageSerializeFn;
+ this.binaryWriterFn = binaryWriterFn;
/** @const */
- this.binaryMessageDeserializeFn = opt_binaryMessageDeserializeFn;
+ this.binaryMessageSerializeFn = binaryMessageSerializeFn;
/** @const */
- this.isRepeated = isRepeated;
+ this.binaryMessageDeserializeFn = binaryMessageDeserializeFn;
/** @const */
- this.isPacked = opt_isPacked;
+ this.isPacked = isPacked;
};
-
/**
* @return {boolean} Does this field represent a sub Message?
*/
@@ -491,11 +502,13 @@ jspb.Message.toObjectExtension = function(proto, obj, extensions,
jspb.Message.serializeBinaryExtensions = function(proto, writer, extensions,
getExtensionFn) {
for (var fieldNumber in extensions) {
- var fieldInfo = extensions[fieldNumber];
+ var binaryFieldInfo = extensions[fieldNumber];
+ var fieldInfo = binaryFieldInfo.fieldInfo;
+
// The old codegen doesn't add the extra fields to ExtensionFieldInfo, so we
// need to gracefully error-out here rather than produce a null dereference
// below.
- if (!fieldInfo.binaryWriterFn) {
+ if (!binaryFieldInfo.binaryWriterFn) {
throw new Error('Message extension present that was generated ' +
'without binary serialization support');
}
@@ -508,16 +521,17 @@ jspb.Message.serializeBinaryExtensions = function(proto, writer, extensions,
// message may require binary support, so we can *only* catch this error
// here, at runtime (and this decoupled codegen is the whole point of
// extensions!).
- if (fieldInfo.binaryMessageSerializeFn) {
- fieldInfo.binaryWriterFn.call(writer, fieldInfo.fieldIndex,
- value, fieldInfo.binaryMessageSerializeFn);
+ if (binaryFieldInfo.binaryMessageSerializeFn) {
+ binaryFieldInfo.binaryWriterFn.call(writer, fieldInfo.fieldIndex,
+ value, binaryFieldInfo.binaryMessageSerializeFn);
} else {
throw new Error('Message extension present holding submessage ' +
'without binary support enabled, and message is ' +
'being serialized to binary format');
}
} else {
- fieldInfo.binaryWriterFn.call(writer, fieldInfo.fieldIndex, value);
+ binaryFieldInfo.binaryWriterFn.call(
+ writer, fieldInfo.fieldIndex, value);
}
}
}
@@ -535,12 +549,13 @@ jspb.Message.serializeBinaryExtensions = function(proto, writer, extensions,
*/
jspb.Message.readBinaryExtension = function(msg, reader, extensions,
getExtensionFn, setExtensionFn) {
- var fieldInfo = extensions[reader.getFieldNumber()];
- if (!fieldInfo) {
+ var binaryFieldInfo = extensions[reader.getFieldNumber()];
+ var fieldInfo = binaryFieldInfo.fieldInfo;
+ if (!binaryFieldInfo) {
reader.skipField();
return;
}
- if (!fieldInfo.binaryReaderFn) {
+ if (!binaryFieldInfo.binaryReaderFn) {
throw new Error('Deserializing extension whose generated code does not ' +
'support binary format');
}
@@ -548,14 +563,14 @@ jspb.Message.readBinaryExtension = function(msg, reader, extensions,
var value;
if (fieldInfo.isMessageType()) {
value = new fieldInfo.ctor();
- fieldInfo.binaryReaderFn.call(
- reader, value, fieldInfo.binaryMessageDeserializeFn);
+ binaryFieldInfo.binaryReaderFn.call(
+ reader, value, binaryFieldInfo.binaryMessageDeserializeFn);
} else {
// All other types.
- value = fieldInfo.binaryReaderFn.call(reader);
+ value = binaryFieldInfo.binaryReaderFn.call(reader);
}
- if (fieldInfo.isRepeated && !fieldInfo.isPacked) {
+ if (fieldInfo.isRepeated && !binaryFieldInfo.isPacked) {
var currentList = getExtensionFn.call(msg, fieldInfo);
if (!currentList) {
setExtensionFn.call(msg, fieldInfo, [value]);
@@ -747,29 +762,16 @@ jspb.Message.getFieldProto3 = function(msg, fieldNumber, defaultValue) {
* of serialization/parsing callbacks (which are required by the map at
* construction time, and the map may be constructed here).
*
- * The below callbacks are used to allow the map to serialize and parse its
- * binary wire format data. Their purposes are described in more detail in
- * `jspb.Map`'s constructor documentation.
- *
* @template K, V
* @param {!jspb.Message} msg
* @param {number} fieldNumber
* @param {boolean|undefined} noLazyCreate
* @param {?=} opt_valueCtor
- * @param {function(number,K)=} opt_keyWriterFn
- * @param {function():K=} opt_keyReaderFn
- * @param {function(number,V)|function(number,V,?)|
- * function(number,V,?,?,?,?)=} opt_valueWriterFn
- * @param {function():V|
- * function(V,function(?,?))=} opt_valueReaderFn
- * @param {function(?,?)|function(?,?,?,?,?)=} opt_valueWriterCallback
- * @param {function(?,?)=} opt_valueReaderCallback
* @return {!jspb.Map<K, V>|undefined}
* @protected
*/
jspb.Message.getMapField = function(msg, fieldNumber, noLazyCreate,
- opt_valueCtor, opt_keyWriterFn, opt_keyReaderFn, opt_valueWriterFn,
- opt_valueReaderFn, opt_valueWriterCallback, opt_valueReaderCallback) {
+ opt_valueCtor) {
if (!msg.wrappers_) {
msg.wrappers_ = {};
}
@@ -787,10 +789,7 @@ jspb.Message.getMapField = function(msg, fieldNumber, noLazyCreate,
}
return msg.wrappers_[fieldNumber] =
new jspb.Map(
- /** @type {!Array<!Array<!Object>>} */ (arr),
- opt_keyWriterFn, opt_keyReaderFn, opt_valueWriterFn,
- opt_valueReaderFn, opt_valueCtor, opt_valueWriterCallback,
- opt_valueReaderCallback);
+ /** @type {!Array<!Array<!Object>>} */ (arr), opt_valueCtor);
}
};
diff --git a/js/message_test.js b/js/message_test.js
index 0b0c0172..b7791431 100644
--- a/js/message_test.js
+++ b/js/message_test.js
@@ -215,6 +215,10 @@ describe('Message test suite', function() {
assertEquals(true, response.getBoolField());
assertEquals(11, response.getIntField());
assertEquals(13, response.getEnumField());
+ assertFalse(response.hasStringField());
+ assertFalse(response.hasBoolField());
+ assertFalse(response.hasIntField());
+ assertFalse(response.hasEnumField());
// Test with null values, as would be returned by a JSON serializer.
response = makeDefault([null, null, null, null]);
@@ -222,6 +226,10 @@ describe('Message test suite', function() {
assertEquals(true, response.getBoolField());
assertEquals(11, response.getIntField());
assertEquals(13, response.getEnumField());
+ assertFalse(response.hasStringField());
+ assertFalse(response.hasBoolField());
+ assertFalse(response.hasIntField());
+ assertFalse(response.hasEnumField());
// Test with false-like values.
response = makeDefault(['', false, 0, 0]);
@@ -229,6 +237,10 @@ describe('Message test suite', function() {
assertEquals(false, response.getBoolField());
assertEquals(true, response.getIntField() == 0);
assertEquals(true, response.getEnumField() == 0);
+ assertTrue(response.hasStringField());
+ assertTrue(response.hasBoolField());
+ assertTrue(response.hasIntField());
+ assertTrue(response.hasEnumField());
// Test that clearing the values reverts them to the default state.
response = makeDefault(['blah', false, 111, 77]);
@@ -238,6 +250,10 @@ describe('Message test suite', function() {
assertEquals(true, response.getBoolField());
assertEquals(11, response.getIntField());
assertEquals(13, response.getEnumField());
+ assertFalse(response.hasStringField());
+ assertFalse(response.hasBoolField());
+ assertFalse(response.hasIntField());
+ assertFalse(response.hasEnumField());
// Test that setFoo(null) clears the values.
response = makeDefault(['blah', false, 111, 77]);
@@ -247,6 +263,10 @@ describe('Message test suite', function() {
assertEquals(true, response.getBoolField());
assertEquals(11, response.getIntField());
assertEquals(13, response.getEnumField());
+ assertFalse(response.hasStringField());
+ assertFalse(response.hasBoolField());
+ assertFalse(response.hasIntField());
+ assertFalse(response.hasEnumField());
});
it('testMessageRegistration', function() {
@@ -256,9 +276,6 @@ describe('Message test suite', function() {
});
it('testClearFields', function() {
- // We don't set 'proper' defaults, rather, bools, strings,
- // etc, are cleared to undefined or null and take on the Javascript
- // meaning for that value. Repeated fields are set to [] when cleared.
var data = ['str', true, [11], [[22], [33]], ['s1', 's2']];
var foo = new proto.jspb.test.OptionalFields(data);
foo.clearAString();
@@ -266,9 +283,11 @@ describe('Message test suite', function() {
foo.clearANestedMessage();
foo.clearARepeatedMessageList();
foo.clearARepeatedStringList();
- assertUndefined(foo.getAString());
- assertUndefined(foo.getABool());
+ assertEquals('', foo.getAString());
+ assertEquals(false, foo.getABool());
assertUndefined(foo.getANestedMessage());
+ assertFalse(foo.hasAString());
+ assertFalse(foo.hasABool());
assertObjectEquals([], foo.getARepeatedMessageList());
assertObjectEquals([], foo.getARepeatedStringList());
// NOTE: We want the missing fields in 'expected' to be undefined,
@@ -288,9 +307,11 @@ describe('Message test suite', function() {
foo.setANestedMessage(null);
foo.setARepeatedMessageList(null);
foo.setARepeatedStringList(null);
- assertNull(foo.getAString());
- assertNull(foo.getABool());
+ assertEquals('', foo.getAString());
+ assertEquals(false, foo.getABool());
assertNull(foo.getANestedMessage());
+ assertFalse(foo.hasAString());
+ assertFalse(foo.hasABool());
assertObjectEquals([], foo.getARepeatedMessageList());
assertObjectEquals([], foo.getARepeatedStringList());
assertObjectEquals([null, null, null, [], []], foo.toArray());
@@ -304,9 +325,11 @@ describe('Message test suite', function() {
foo.setANestedMessage(undefined);
foo.setARepeatedMessageList(undefined);
foo.setARepeatedStringList(undefined);
- assertUndefined(foo.getAString());
- assertUndefined(foo.getABool());
+ assertEquals('', foo.getAString());
+ assertEquals(false, foo.getABool());
assertUndefined(foo.getANestedMessage());
+ assertFalse(foo.hasAString());
+ assertFalse(foo.hasABool());
assertObjectEquals([], foo.getARepeatedMessageList());
assertObjectEquals([], foo.getARepeatedStringList());
expected = [,,, [], []];
@@ -320,9 +343,9 @@ describe('Message test suite', function() {
{1000: 'unique'}]);
var diff = /** @type {proto.jspb.test.HasExtensions} */
(jspb.Message.difference(p1, p2));
- assertUndefined(diff.getStr1());
+ assertEquals('', diff.getStr1());
assertEquals('what', diff.getStr2());
- assertUndefined(diff.getStr3());
+ assertEquals('', diff.getStr3());
assertEquals('unique', diff.extensionObject_[1000]);
});
@@ -780,7 +803,7 @@ describe('Message test suite', function() {
var message = new proto.jspb.test.TestMessageWithOneof([,, 'x']);
assertEquals('x', message.getPone());
- assertUndefined(message.getPthree());
+ assertEquals('', message.getPthree());
assertEquals(
proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
message.getPartialOneofCase());
@@ -789,7 +812,7 @@ describe('Message test suite', function() {
it('testKeepsLastWireValueSetInUnion_multipleValues', function() {
var message = new proto.jspb.test.TestMessageWithOneof([,, 'x',, 'y']);
- assertUndefined('x', message.getPone());
+ assertEquals('', message.getPone());
assertEquals('y', message.getPthree());
assertEquals(
proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE,
@@ -798,35 +821,47 @@ describe('Message test suite', function() {
it('testSettingOneofFieldClearsOthers', function() {
var message = new proto.jspb.test.TestMessageWithOneof;
- assertUndefined(message.getPone());
- assertUndefined(message.getPthree());
+ assertEquals('', message.getPone());
+ assertEquals('', message.getPthree());
+ assertFalse(message.hasPone());
+ assertFalse(message.hasPthree());
message.setPone('hi');
assertEquals('hi', message.getPone());
- assertUndefined(message.getPthree());
+ assertEquals('', message.getPthree());
+ assertTrue(message.hasPone());
+ assertFalse(message.hasPthree());
message.setPthree('bye');
- assertUndefined(message.getPone());
+ assertEquals('', message.getPone());
assertEquals('bye', message.getPthree());
+ assertFalse(message.hasPone());
+ assertTrue(message.hasPthree());
});
it('testSettingOneofFieldDoesNotClearFieldsFromOtherUnions', function() {
var other = new proto.jspb.test.TestMessageWithOneof;
var message = new proto.jspb.test.TestMessageWithOneof;
- assertUndefined(message.getPone());
- assertUndefined(message.getPthree());
+ assertEquals('', message.getPone());
+ assertEquals('', message.getPthree());
assertUndefined(message.getRone());
+ assertFalse(message.hasPone());
+ assertFalse(message.hasPthree());
message.setPone('hi');
message.setRone(other);
assertEquals('hi', message.getPone());
- assertUndefined(message.getPthree());
+ assertEquals('', message.getPthree());
assertEquals(other, message.getRone());
+ assertTrue(message.hasPone());
+ assertFalse(message.hasPthree());
message.setPthree('bye');
- assertUndefined(message.getPone());
+ assertEquals('', message.getPone());
assertEquals('bye', message.getPthree());
assertEquals(other, message.getRone());
+ assertFalse(message.hasPone());
+ assertTrue(message.hasPthree());
});
it('testUnsetsOneofCaseWhenFieldIsCleared', function() {
@@ -851,7 +886,7 @@ describe('Message test suite', function() {
it('testMessageWithDefaultOneofValues', function() {
var message = new proto.jspb.test.TestMessageWithOneof;
assertEquals(1234, message.getAone());
- assertUndefined(message.getAtwo());
+ assertEquals(0, message.getAtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofACase
.DEFAULT_ONEOF_A_NOT_SET,
@@ -859,7 +894,7 @@ describe('Message test suite', function() {
message.setAone(567);
assertEquals(567, message.getAone());
- assertUndefined(message.getAtwo());
+ assertEquals(0, message.getAtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.AONE,
message.getDefaultOneofACase());
@@ -873,7 +908,7 @@ describe('Message test suite', function() {
message.clearAtwo();
assertEquals(1234, message.getAone());
- assertUndefined(message.getAtwo());
+ assertEquals(0, message.getAtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofACase
.DEFAULT_ONEOF_A_NOT_SET,
@@ -882,8 +917,10 @@ describe('Message test suite', function() {
it('testMessageWithDefaultOneofValues_defaultNotOnFirstField', function() {
var message = new proto.jspb.test.TestMessageWithOneof;
- assertUndefined(message.getBone());
+ assertEquals(0, message.getBone());
assertEquals(1234, message.getBtwo());
+ assertFalse(message.hasBone());
+ assertFalse(message.hasBtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase
.DEFAULT_ONEOF_B_NOT_SET,
@@ -892,19 +929,25 @@ describe('Message test suite', function() {
message.setBone(2);
assertEquals(2, message.getBone());
assertEquals(1234, message.getBtwo());
+ assertTrue(message.hasBone());
+ assertFalse(message.hasBtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE,
message.getDefaultOneofBCase());
message.setBtwo(3);
- assertUndefined(message.getBone());
+ assertEquals(0, message.getBone());
+ assertFalse(message.hasBone());
+ assertTrue(message.hasBtwo());
assertEquals(3, message.getBtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
message.getDefaultOneofBCase());
message.clearBtwo();
- assertUndefined(message.getBone());
+ assertEquals(0, message.getBone());
+ assertFalse(message.hasBone());
+ assertFalse(message.hasBtwo());
assertEquals(1234, message.getBtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase
@@ -916,7 +959,7 @@ describe('Message test suite', function() {
var message =
new proto.jspb.test.TestMessageWithOneof(new Array(9).concat(567));
assertEquals(567, message.getAone());
- assertUndefined(message.getAtwo());
+ assertEquals(0, message.getAtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.AONE,
message.getDefaultOneofACase());
@@ -952,7 +995,7 @@ describe('Message test suite', function() {
message =
new proto.jspb.test.TestMessageWithOneof(new Array(12).concat(890));
- assertUndefined(message.getBone());
+ assertEquals(0, message.getBone());
assertEquals(890, message.getBtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
@@ -960,7 +1003,7 @@ describe('Message test suite', function() {
message = new proto.jspb.test.TestMessageWithOneof(
new Array(11).concat(567, 890));
- assertUndefined(message.getBone());
+ assertEquals(0, message.getBone());
assertEquals(890, message.getBtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
@@ -977,7 +1020,7 @@ describe('Message test suite', function() {
var other = new proto.jspb.test.TestMessageWithOneof;
message.setRone(other);
assertEquals(other, message.getRone());
- assertUndefined(message.getRtwo());
+ assertEquals('', message.getRtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.RONE,
message.getRecursiveOneofCase());
@@ -995,7 +1038,7 @@ describe('Message test suite', function() {
var message = new proto.jspb.test.TestMessageWithOneof;
message.setPone('x');
assertEquals('x', message.getPone());
- assertUndefined(message.getPthree());
+ assertEquals('', message.getPthree());
assertEquals(
proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
message.getPartialOneofCase());
diff --git a/js/package.json b/js/package.json
index 657b08bd..3f51d96b 100644
--- a/js/package.json
+++ b/js/package.json
@@ -1,6 +1,6 @@
{
"name": "google-protobuf",
- "version": "3.0.0-alpha.6.2",
+ "version": "3.0.0",
"description": "Protocol Buffers for JavaScript",
"main": "google-protobuf.js",
"files": [
diff --git a/js/proto3_test.js b/js/proto3_test.js
index 4dd7790f..fab0fd44 100644
--- a/js/proto3_test.js
+++ b/js/proto3_test.js
@@ -221,37 +221,52 @@ describe('proto3Test', function() {
it('testOneofs', function() {
var msg = new proto.jspb.test.TestProto3();
- assertEquals(msg.getOneofUint32(), undefined);
+ assertEquals(msg.getOneofUint32(), 0);
assertEquals(msg.getOneofForeignMessage(), undefined);
- assertEquals(msg.getOneofString(), undefined);
- assertEquals(msg.getOneofBytes(), undefined);
+ assertEquals(msg.getOneofString(), '');
+ assertEquals(msg.getOneofBytes(), '');
+ assertFalse(msg.hasOneofUint32());
+ assertFalse(msg.hasOneofString());
+ assertFalse(msg.hasOneofBytes());
msg.setOneofUint32(42);
assertEquals(msg.getOneofUint32(), 42);
assertEquals(msg.getOneofForeignMessage(), undefined);
- assertEquals(msg.getOneofString(), undefined);
- assertEquals(msg.getOneofBytes(), undefined);
+ assertEquals(msg.getOneofString(), '');
+ assertEquals(msg.getOneofBytes(), '');
+ assertTrue(msg.hasOneofUint32());
+ assertFalse(msg.hasOneofString());
+ assertFalse(msg.hasOneofBytes());
var submsg = new proto.jspb.test.ForeignMessage();
msg.setOneofForeignMessage(submsg);
- assertEquals(msg.getOneofUint32(), undefined);
+ assertEquals(msg.getOneofUint32(), 0);
assertEquals(msg.getOneofForeignMessage(), submsg);
- assertEquals(msg.getOneofString(), undefined);
- assertEquals(msg.getOneofBytes(), undefined);
+ assertEquals(msg.getOneofString(), '');
+ assertEquals(msg.getOneofBytes(), '');
+ assertFalse(msg.hasOneofUint32());
+ assertFalse(msg.hasOneofString());
+ assertFalse(msg.hasOneofBytes());
msg.setOneofString('hello');
- assertEquals(msg.getOneofUint32(), undefined);
+ assertEquals(msg.getOneofUint32(), 0);
assertEquals(msg.getOneofForeignMessage(), undefined);
assertEquals(msg.getOneofString(), 'hello');
- assertEquals(msg.getOneofBytes(), undefined);
+ assertEquals(msg.getOneofBytes(), '');
+ assertFalse(msg.hasOneofUint32());
+ assertTrue(msg.hasOneofString());
+ assertFalse(msg.hasOneofBytes());
msg.setOneofBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
- assertEquals(msg.getOneofUint32(), undefined);
+ assertEquals(msg.getOneofUint32(), 0);
assertEquals(msg.getOneofForeignMessage(), undefined);
- assertEquals(msg.getOneofString(), undefined);
+ assertEquals(msg.getOneofString(), '');
assertEquals(msg.getOneofBytes_asB64(),
goog.crypt.base64.encodeString('\u00FF\u00FF'));
+ assertFalse(msg.hasOneofUint32());
+ assertFalse(msg.hasOneofString());
+ assertTrue(msg.hasOneofBytes());
});
diff --git a/js/test.proto b/js/test.proto
index cf2eafef..937ffb89 100644
--- a/js/test.proto
+++ b/js/test.proto
@@ -233,3 +233,4 @@ message TestEndsWithBytes {
optional int32 value = 1;
optional bytes data = 2;
}
+
diff --git a/objectivec/DevTools/compile_testing_protos.sh b/objectivec/DevTools/compile_testing_protos.sh
index 82953130..6cc32da9 100755
--- a/objectivec/DevTools/compile_testing_protos.sh
+++ b/objectivec/DevTools/compile_testing_protos.sh
@@ -1,17 +1,16 @@
-#!/bin/bash
-
+#!/bin/bash -eu
# Invoked by the Xcode projects to build the protos needed for the unittests.
-set -eu
-
readonly OUTPUT_DIR="${PROJECT_DERIVED_FILE_DIR}/protos"
+# -----------------------------------------------------------------------------
# Helper for bailing.
die() {
echo "Error: $1"
exit 2
}
+# -----------------------------------------------------------------------------
# What to do.
case "${ACTION}" in
"")
@@ -26,12 +25,19 @@ case "${ACTION}" in
;;
esac
-# Move to the top of the protobuf directories.
-cd "${SRCROOT}/.."
+# -----------------------------------------------------------------------------
+# Ensure the output dir exists
+mkdir -p "${OUTPUT_DIR}/google/protobuf"
+# -----------------------------------------------------------------------------
+# Move to the top of the protobuf directories and ensure there is a protoc
+# binary to use.
+cd "${SRCROOT}/.."
[[ -x src/protoc ]] || \
die "Could not find the protoc binary; make sure you have built it (objectivec/DevTools/full_mac_build.sh -h)."
+# -----------------------------------------------------------------------------
+# See the compiler or proto files have changed.
RUN_PROTOC=no
if [[ ! -d "${OUTPUT_DIR}" ]] ; then
RUN_PROTOC=yes
@@ -50,7 +56,7 @@ else
# Find the oldest output file.
readonly OldestOutput=$(find \
"${OUTPUT_DIR}" \
- -type f -print0 \
+ -type f -name "*pbobjc.[hm]" -print0 \
| xargs -0 stat -f "%m %N" \
| sort -n -r | tail -n1 | cut -f2- -d" ")
# If the newest input is newer than the oldest output, regenerate.
@@ -64,10 +70,30 @@ if [[ "${RUN_PROTOC}" != "yes" ]] ; then
exit 0
fi
-# Ensure the output dir exists
-mkdir -p "${OUTPUT_DIR}/google/protobuf"
+# -----------------------------------------------------------------------------
+# Prune out all the files from previous generations to ensure we only have
+# current ones.
+find "${OUTPUT_DIR}" \
+ -type f -name "*pbobjc.[hm]" -print0 \
+ | xargs -0 rm -rf
+
+# -----------------------------------------------------------------------------
+# Helper to invoke protoc
+compile_protos() {
+ src/protoc \
+ --objc_out="${OUTPUT_DIR}/google/protobuf" \
+ --proto_path=src/google/protobuf/ \
+ --proto_path=src \
+ "$@"
+}
+
+# -----------------------------------------------------------------------------
+# Generate most of the proto files that exist in the C++ src tree. Several
+# are used in the tests, but the extra don't hurt in that they ensure ObjC
+# sources can be generated from them.
CORE_PROTO_FILES=(
+ src/google/protobuf/any_test.proto
src/google/protobuf/unittest_arena.proto
src/google/protobuf/unittest_custom_options.proto
src/google/protobuf/unittest_enormous_descriptor.proto
@@ -90,35 +116,32 @@ CORE_PROTO_FILES=(
src/google/protobuf/map_lite_unittest.proto
src/google/protobuf/map_proto2_unittest.proto
src/google/protobuf/map_unittest.proto
-)
-
-# The unittest_custom_options.proto extends the messages in descriptor.proto
-# so we build it in to test extending in general. The library doesn't provide
-# a descriptor as it doesn't use the classes/enums.
-CORE_PROTO_FILES+=(
+ # The unittest_custom_options.proto extends the messages in descriptor.proto
+ # so we build it in to test extending in general. The library doesn't provide
+ # a descriptor as it doesn't use the classes/enums.
src/google/protobuf/descriptor.proto
)
-compile_proto() {
- src/protoc \
- --objc_out="${OUTPUT_DIR}/google/protobuf" \
- --proto_path=src/google/protobuf/ \
- --proto_path=src \
- $*
-}
-
+# Note: there is overlap in package.Message names between some of the test
+# files, so they can't be generated all at once. This works because the overlap
+# isn't linked into a single binary.
for a_proto in "${CORE_PROTO_FILES[@]}" ; do
- compile_proto "${a_proto}"
+ compile_protos "${a_proto}"
done
-OBJC_PROTO_FILES=(
- objectivec/Tests/unittest_cycle.proto
- objectivec/Tests/unittest_runtime_proto2.proto
- objectivec/Tests/unittest_runtime_proto3.proto
- objectivec/Tests/unittest_objc.proto
+# -----------------------------------------------------------------------------
+# Generate the Objective C specific testing protos.
+compile_protos \
+ --proto_path="objectivec/Tests" \
+ objectivec/Tests/unittest_cycle.proto \
+ objectivec/Tests/unittest_extension_chain_a.proto \
+ objectivec/Tests/unittest_extension_chain_b.proto \
+ objectivec/Tests/unittest_extension_chain_c.proto \
+ objectivec/Tests/unittest_extension_chain_d.proto \
+ objectivec/Tests/unittest_extension_chain_e.proto \
+ objectivec/Tests/unittest_extension_chain_f.proto \
+ objectivec/Tests/unittest_extension_chain_g.proto \
+ objectivec/Tests/unittest_runtime_proto2.proto \
+ objectivec/Tests/unittest_runtime_proto3.proto \
+ objectivec/Tests/unittest_objc.proto \
objectivec/Tests/unittest_objc_startup.proto
-)
-
-for a_proto in "${OBJC_PROTO_FILES[@]}" ; do
- compile_proto --proto_path="objectivec/Tests" "${a_proto}"
-done
diff --git a/objectivec/GPBArray.h b/objectivec/GPBArray.h
index afda57f3..781cfb6f 100644
--- a/objectivec/GPBArray.h
+++ b/objectivec/GPBArray.h
@@ -32,11 +32,6 @@
#import "GPBRuntimeTypes.h"
-// These classes are used for repeated fields of basic data types. They are used because
-// they perform better than boxing into NSNumbers in NSArrays.
-
-// Note: These are not meant to be subclassed.
-
NS_ASSUME_NONNULL_BEGIN
//%PDDM-EXPAND DECLARE_ARRAYS()
@@ -44,39 +39,171 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Int32
+/**
+ * Class used for repeated fields of int32_t values. This performs better than
+ * boxing into NSNumbers in NSArrays.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt32Array : NSObject <NSCopying>
+/** The number of elements contained in the array. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty GPBInt32Array.
+ **/
+ (instancetype)array;
+
+/**
+ * Creates and initializes a GPBInt32Array with the single element given.
+ *
+ * @param value The value to be placed in the array.
+ *
+ * @return A newly instanced GPBInt32Array with value in it.
+ **/
+ (instancetype)arrayWithValue:(int32_t)value;
+
+/**
+ * Creates and initializes a GPBInt32Array with the contents of the given
+ * array.
+ *
+ * @param array Array with the contents to be put into the new array.
+ *
+ * @return A newly instanced GPBInt32Array with the contents of array.
+ **/
+ (instancetype)arrayWithValueArray:(GPBInt32Array *)array;
+
+/**
+ * Creates and initializes a GPBInt32Array with the given capacity.
+ *
+ * @param count The capacity needed for the array.
+ *
+ * @return A newly instanced GPBInt32Array with a capacity of count.
+ **/
+ (instancetype)arrayWithCapacity:(NSUInteger)count;
+/**
+ * @return A newly initialized and empty GPBInt32Array.
+ **/
- (instancetype)init NS_DESIGNATED_INITIALIZER;
-// Initializes the array, copying the values.
+
+/**
+ * Initializes the array, copying the given values.
+ *
+ * @param values An array with the values to put inside this array.
+ * @param count The number of elements to copy into the array.
+ *
+ * @return A newly initialized GPBInt32Array with a copy of the values.
+ **/
- (instancetype)initWithValues:(const int32_t [])values
count:(NSUInteger)count;
+
+/**
+ * Initializes the array, copying the given values.
+ *
+ * @param array An array with the values to put inside this array.
+ *
+ * @return A newly initialized GPBInt32Array with a copy of the values.
+ **/
- (instancetype)initWithValueArray:(GPBInt32Array *)array;
+
+/**
+ * Initializes the array with the given capacity.
+ *
+ * @param count The capacity needed for the array.
+ *
+ * @return A newly initialized GPBInt32Array with a capacity of count.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)count;
+/**
+ * Gets the value at the given index.
+ *
+ * @param index The index of the value to get.
+ *
+ * @return The value at the given index.
+ **/
- (int32_t)valueAtIndex:(NSUInteger)index;
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param opts Options to control the enumeration.
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+/**
+ * Adds a value to this array.
+ *
+ * @param value The value to add to this array.
+ **/
- (void)addValue:(int32_t)value;
+
+/**
+ * Adds values to this array.
+ *
+ * @param values The values to add to this array.
+ * @param count The number of elements to add.
+ **/
- (void)addValues:(const int32_t [])values count:(NSUInteger)count;
+
+/**
+ * Adds the values from the given array to this array.
+ *
+ * @param array The array containing the elements to add to this array.
+ **/
- (void)addValuesFromArray:(GPBInt32Array *)array;
+/**
+ * Inserts a value into the given position.
+ *
+ * @param value The value to add to this array.
+ * @param index The index into which to insert the value.
+ **/
- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index;
+/**
+ * Replaces the value at the given index with the given value.
+ *
+ * @param index The index for which to replace the value.
+ * @param value The value to replace with.
+ **/
- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value;
+/**
+ * Removes the value at the given index.
+ *
+ * @param index The index of the value to remove.
+ **/
- (void)removeValueAtIndex:(NSUInteger)index;
+
+/**
+ * Removes all the values from this array.
+ **/
- (void)removeAll;
+/**
+ * Exchanges the values between the given indexes.
+ *
+ * @param idx1 The index of the first element to exchange.
+ * @param idx2 The index of the second element to exchange.
+ **/
- (void)exchangeValueAtIndex:(NSUInteger)idx1
withValueAtIndex:(NSUInteger)idx2;
@@ -84,39 +211,171 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - UInt32
+/**
+ * Class used for repeated fields of uint32_t values. This performs better than
+ * boxing into NSNumbers in NSArrays.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt32Array : NSObject <NSCopying>
+/** The number of elements contained in the array. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty GPBUInt32Array.
+ **/
+ (instancetype)array;
+
+/**
+ * Creates and initializes a GPBUInt32Array with the single element given.
+ *
+ * @param value The value to be placed in the array.
+ *
+ * @return A newly instanced GPBUInt32Array with value in it.
+ **/
+ (instancetype)arrayWithValue:(uint32_t)value;
+
+/**
+ * Creates and initializes a GPBUInt32Array with the contents of the given
+ * array.
+ *
+ * @param array Array with the contents to be put into the new array.
+ *
+ * @return A newly instanced GPBUInt32Array with the contents of array.
+ **/
+ (instancetype)arrayWithValueArray:(GPBUInt32Array *)array;
+
+/**
+ * Creates and initializes a GPBUInt32Array with the given capacity.
+ *
+ * @param count The capacity needed for the array.
+ *
+ * @return A newly instanced GPBUInt32Array with a capacity of count.
+ **/
+ (instancetype)arrayWithCapacity:(NSUInteger)count;
+/**
+ * @return A newly initialized and empty GPBUInt32Array.
+ **/
- (instancetype)init NS_DESIGNATED_INITIALIZER;
-// Initializes the array, copying the values.
+
+/**
+ * Initializes the array, copying the given values.
+ *
+ * @param values An array with the values to put inside this array.
+ * @param count The number of elements to copy into the array.
+ *
+ * @return A newly initialized GPBUInt32Array with a copy of the values.
+ **/
- (instancetype)initWithValues:(const uint32_t [])values
count:(NSUInteger)count;
+
+/**
+ * Initializes the array, copying the given values.
+ *
+ * @param array An array with the values to put inside this array.
+ *
+ * @return A newly initialized GPBUInt32Array with a copy of the values.
+ **/
- (instancetype)initWithValueArray:(GPBUInt32Array *)array;
+
+/**
+ * Initializes the array with the given capacity.
+ *
+ * @param count The capacity needed for the array.
+ *
+ * @return A newly initialized GPBUInt32Array with a capacity of count.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)count;
+/**
+ * Gets the value at the given index.
+ *
+ * @param index The index of the value to get.
+ *
+ * @return The value at the given index.
+ **/
- (uint32_t)valueAtIndex:(NSUInteger)index;
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateValuesWithBlock:(void (^)(uint32_t value, NSUInteger idx, BOOL *stop))block;
+
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param opts Options to control the enumeration.
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
usingBlock:(void (^)(uint32_t value, NSUInteger idx, BOOL *stop))block;
+/**
+ * Adds a value to this array.
+ *
+ * @param value The value to add to this array.
+ **/
- (void)addValue:(uint32_t)value;
+
+/**
+ * Adds values to this array.
+ *
+ * @param values The values to add to this array.
+ * @param count The number of elements to add.
+ **/
- (void)addValues:(const uint32_t [])values count:(NSUInteger)count;
+
+/**
+ * Adds the values from the given array to this array.
+ *
+ * @param array The array containing the elements to add to this array.
+ **/
- (void)addValuesFromArray:(GPBUInt32Array *)array;
+/**
+ * Inserts a value into the given position.
+ *
+ * @param value The value to add to this array.
+ * @param index The index into which to insert the value.
+ **/
- (void)insertValue:(uint32_t)value atIndex:(NSUInteger)index;
+/**
+ * Replaces the value at the given index with the given value.
+ *
+ * @param index The index for which to replace the value.
+ * @param value The value to replace with.
+ **/
- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint32_t)value;
+/**
+ * Removes the value at the given index.
+ *
+ * @param index The index of the value to remove.
+ **/
- (void)removeValueAtIndex:(NSUInteger)index;
+
+/**
+ * Removes all the values from this array.
+ **/
- (void)removeAll;
+/**
+ * Exchanges the values between the given indexes.
+ *
+ * @param idx1 The index of the first element to exchange.
+ * @param idx2 The index of the second element to exchange.
+ **/
- (void)exchangeValueAtIndex:(NSUInteger)idx1
withValueAtIndex:(NSUInteger)idx2;
@@ -124,39 +383,171 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Int64
+/**
+ * Class used for repeated fields of int64_t values. This performs better than
+ * boxing into NSNumbers in NSArrays.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt64Array : NSObject <NSCopying>
+/** The number of elements contained in the array. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty GPBInt64Array.
+ **/
+ (instancetype)array;
+
+/**
+ * Creates and initializes a GPBInt64Array with the single element given.
+ *
+ * @param value The value to be placed in the array.
+ *
+ * @return A newly instanced GPBInt64Array with value in it.
+ **/
+ (instancetype)arrayWithValue:(int64_t)value;
+
+/**
+ * Creates and initializes a GPBInt64Array with the contents of the given
+ * array.
+ *
+ * @param array Array with the contents to be put into the new array.
+ *
+ * @return A newly instanced GPBInt64Array with the contents of array.
+ **/
+ (instancetype)arrayWithValueArray:(GPBInt64Array *)array;
+
+/**
+ * Creates and initializes a GPBInt64Array with the given capacity.
+ *
+ * @param count The capacity needed for the array.
+ *
+ * @return A newly instanced GPBInt64Array with a capacity of count.
+ **/
+ (instancetype)arrayWithCapacity:(NSUInteger)count;
+/**
+ * @return A newly initialized and empty GPBInt64Array.
+ **/
- (instancetype)init NS_DESIGNATED_INITIALIZER;
-// Initializes the array, copying the values.
+
+/**
+ * Initializes the array, copying the given values.
+ *
+ * @param values An array with the values to put inside this array.
+ * @param count The number of elements to copy into the array.
+ *
+ * @return A newly initialized GPBInt64Array with a copy of the values.
+ **/
- (instancetype)initWithValues:(const int64_t [])values
count:(NSUInteger)count;
+
+/**
+ * Initializes the array, copying the given values.
+ *
+ * @param array An array with the values to put inside this array.
+ *
+ * @return A newly initialized GPBInt64Array with a copy of the values.
+ **/
- (instancetype)initWithValueArray:(GPBInt64Array *)array;
+
+/**
+ * Initializes the array with the given capacity.
+ *
+ * @param count The capacity needed for the array.
+ *
+ * @return A newly initialized GPBInt64Array with a capacity of count.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)count;
+/**
+ * Gets the value at the given index.
+ *
+ * @param index The index of the value to get.
+ *
+ * @return The value at the given index.
+ **/
- (int64_t)valueAtIndex:(NSUInteger)index;
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateValuesWithBlock:(void (^)(int64_t value, NSUInteger idx, BOOL *stop))block;
+
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param opts Options to control the enumeration.
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
usingBlock:(void (^)(int64_t value, NSUInteger idx, BOOL *stop))block;
+/**
+ * Adds a value to this array.
+ *
+ * @param value The value to add to this array.
+ **/
- (void)addValue:(int64_t)value;
+
+/**
+ * Adds values to this array.
+ *
+ * @param values The values to add to this array.
+ * @param count The number of elements to add.
+ **/
- (void)addValues:(const int64_t [])values count:(NSUInteger)count;
+
+/**
+ * Adds the values from the given array to this array.
+ *
+ * @param array The array containing the elements to add to this array.
+ **/
- (void)addValuesFromArray:(GPBInt64Array *)array;
+/**
+ * Inserts a value into the given position.
+ *
+ * @param value The value to add to this array.
+ * @param index The index into which to insert the value.
+ **/
- (void)insertValue:(int64_t)value atIndex:(NSUInteger)index;
+/**
+ * Replaces the value at the given index with the given value.
+ *
+ * @param index The index for which to replace the value.
+ * @param value The value to replace with.
+ **/
- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int64_t)value;
+/**
+ * Removes the value at the given index.
+ *
+ * @param index The index of the value to remove.
+ **/
- (void)removeValueAtIndex:(NSUInteger)index;
+
+/**
+ * Removes all the values from this array.
+ **/
- (void)removeAll;
+/**
+ * Exchanges the values between the given indexes.
+ *
+ * @param idx1 The index of the first element to exchange.
+ * @param idx2 The index of the second element to exchange.
+ **/
- (void)exchangeValueAtIndex:(NSUInteger)idx1
withValueAtIndex:(NSUInteger)idx2;
@@ -164,39 +555,171 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - UInt64
+/**
+ * Class used for repeated fields of uint64_t values. This performs better than
+ * boxing into NSNumbers in NSArrays.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt64Array : NSObject <NSCopying>
+/** The number of elements contained in the array. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty GPBUInt64Array.
+ **/
+ (instancetype)array;
+
+/**
+ * Creates and initializes a GPBUInt64Array with the single element given.
+ *
+ * @param value The value to be placed in the array.
+ *
+ * @return A newly instanced GPBUInt64Array with value in it.
+ **/
+ (instancetype)arrayWithValue:(uint64_t)value;
+
+/**
+ * Creates and initializes a GPBUInt64Array with the contents of the given
+ * array.
+ *
+ * @param array Array with the contents to be put into the new array.
+ *
+ * @return A newly instanced GPBUInt64Array with the contents of array.
+ **/
+ (instancetype)arrayWithValueArray:(GPBUInt64Array *)array;
+
+/**
+ * Creates and initializes a GPBUInt64Array with the given capacity.
+ *
+ * @param count The capacity needed for the array.
+ *
+ * @return A newly instanced GPBUInt64Array with a capacity of count.
+ **/
+ (instancetype)arrayWithCapacity:(NSUInteger)count;
+/**
+ * @return A newly initialized and empty GPBUInt64Array.
+ **/
- (instancetype)init NS_DESIGNATED_INITIALIZER;
-// Initializes the array, copying the values.
+
+/**
+ * Initializes the array, copying the given values.
+ *
+ * @param values An array with the values to put inside this array.
+ * @param count The number of elements to copy into the array.
+ *
+ * @return A newly initialized GPBUInt64Array with a copy of the values.
+ **/
- (instancetype)initWithValues:(const uint64_t [])values
count:(NSUInteger)count;
+
+/**
+ * Initializes the array, copying the given values.
+ *
+ * @param array An array with the values to put inside this array.
+ *
+ * @return A newly initialized GPBUInt64Array with a copy of the values.
+ **/
- (instancetype)initWithValueArray:(GPBUInt64Array *)array;
+
+/**
+ * Initializes the array with the given capacity.
+ *
+ * @param count The capacity needed for the array.
+ *
+ * @return A newly initialized GPBUInt64Array with a capacity of count.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)count;
+/**
+ * Gets the value at the given index.
+ *
+ * @param index The index of the value to get.
+ *
+ * @return The value at the given index.
+ **/
- (uint64_t)valueAtIndex:(NSUInteger)index;
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateValuesWithBlock:(void (^)(uint64_t value, NSUInteger idx, BOOL *stop))block;
+
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param opts Options to control the enumeration.
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
usingBlock:(void (^)(uint64_t value, NSUInteger idx, BOOL *stop))block;
+/**
+ * Adds a value to this array.
+ *
+ * @param value The value to add to this array.
+ **/
- (void)addValue:(uint64_t)value;
+
+/**
+ * Adds values to this array.
+ *
+ * @param values The values to add to this array.
+ * @param count The number of elements to add.
+ **/
- (void)addValues:(const uint64_t [])values count:(NSUInteger)count;
+
+/**
+ * Adds the values from the given array to this array.
+ *
+ * @param array The array containing the elements to add to this array.
+ **/
- (void)addValuesFromArray:(GPBUInt64Array *)array;
+/**
+ * Inserts a value into the given position.
+ *
+ * @param value The value to add to this array.
+ * @param index The index into which to insert the value.
+ **/
- (void)insertValue:(uint64_t)value atIndex:(NSUInteger)index;
+/**
+ * Replaces the value at the given index with the given value.
+ *
+ * @param index The index for which to replace the value.
+ * @param value The value to replace with.
+ **/
- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint64_t)value;
+/**
+ * Removes the value at the given index.
+ *
+ * @param index The index of the value to remove.
+ **/
- (void)removeValueAtIndex:(NSUInteger)index;
+
+/**
+ * Removes all the values from this array.
+ **/
- (void)removeAll;
+/**
+ * Exchanges the values between the given indexes.
+ *
+ * @param idx1 The index of the first element to exchange.
+ * @param idx2 The index of the second element to exchange.
+ **/
- (void)exchangeValueAtIndex:(NSUInteger)idx1
withValueAtIndex:(NSUInteger)idx2;
@@ -204,39 +727,171 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Float
+/**
+ * Class used for repeated fields of float values. This performs better than
+ * boxing into NSNumbers in NSArrays.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBFloatArray : NSObject <NSCopying>
+/** The number of elements contained in the array. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty GPBFloatArray.
+ **/
+ (instancetype)array;
+
+/**
+ * Creates and initializes a GPBFloatArray with the single element given.
+ *
+ * @param value The value to be placed in the array.
+ *
+ * @return A newly instanced GPBFloatArray with value in it.
+ **/
+ (instancetype)arrayWithValue:(float)value;
+
+/**
+ * Creates and initializes a GPBFloatArray with the contents of the given
+ * array.
+ *
+ * @param array Array with the contents to be put into the new array.
+ *
+ * @return A newly instanced GPBFloatArray with the contents of array.
+ **/
+ (instancetype)arrayWithValueArray:(GPBFloatArray *)array;
+
+/**
+ * Creates and initializes a GPBFloatArray with the given capacity.
+ *
+ * @param count The capacity needed for the array.
+ *
+ * @return A newly instanced GPBFloatArray with a capacity of count.
+ **/
+ (instancetype)arrayWithCapacity:(NSUInteger)count;
+/**
+ * @return A newly initialized and empty GPBFloatArray.
+ **/
- (instancetype)init NS_DESIGNATED_INITIALIZER;
-// Initializes the array, copying the values.
+
+/**
+ * Initializes the array, copying the given values.
+ *
+ * @param values An array with the values to put inside this array.
+ * @param count The number of elements to copy into the array.
+ *
+ * @return A newly initialized GPBFloatArray with a copy of the values.
+ **/
- (instancetype)initWithValues:(const float [])values
count:(NSUInteger)count;
+
+/**
+ * Initializes the array, copying the given values.
+ *
+ * @param array An array with the values to put inside this array.
+ *
+ * @return A newly initialized GPBFloatArray with a copy of the values.
+ **/
- (instancetype)initWithValueArray:(GPBFloatArray *)array;
+
+/**
+ * Initializes the array with the given capacity.
+ *
+ * @param count The capacity needed for the array.
+ *
+ * @return A newly initialized GPBFloatArray with a capacity of count.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)count;
+/**
+ * Gets the value at the given index.
+ *
+ * @param index The index of the value to get.
+ *
+ * @return The value at the given index.
+ **/
- (float)valueAtIndex:(NSUInteger)index;
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateValuesWithBlock:(void (^)(float value, NSUInteger idx, BOOL *stop))block;
+
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param opts Options to control the enumeration.
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
usingBlock:(void (^)(float value, NSUInteger idx, BOOL *stop))block;
+/**
+ * Adds a value to this array.
+ *
+ * @param value The value to add to this array.
+ **/
- (void)addValue:(float)value;
+
+/**
+ * Adds values to this array.
+ *
+ * @param values The values to add to this array.
+ * @param count The number of elements to add.
+ **/
- (void)addValues:(const float [])values count:(NSUInteger)count;
+
+/**
+ * Adds the values from the given array to this array.
+ *
+ * @param array The array containing the elements to add to this array.
+ **/
- (void)addValuesFromArray:(GPBFloatArray *)array;
+/**
+ * Inserts a value into the given position.
+ *
+ * @param value The value to add to this array.
+ * @param index The index into which to insert the value.
+ **/
- (void)insertValue:(float)value atIndex:(NSUInteger)index;
+/**
+ * Replaces the value at the given index with the given value.
+ *
+ * @param index The index for which to replace the value.
+ * @param value The value to replace with.
+ **/
- (void)replaceValueAtIndex:(NSUInteger)index withValue:(float)value;
+/**
+ * Removes the value at the given index.
+ *
+ * @param index The index of the value to remove.
+ **/
- (void)removeValueAtIndex:(NSUInteger)index;
+
+/**
+ * Removes all the values from this array.
+ **/
- (void)removeAll;
+/**
+ * Exchanges the values between the given indexes.
+ *
+ * @param idx1 The index of the first element to exchange.
+ * @param idx2 The index of the second element to exchange.
+ **/
- (void)exchangeValueAtIndex:(NSUInteger)idx1
withValueAtIndex:(NSUInteger)idx2;
@@ -244,39 +899,171 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Double
+/**
+ * Class used for repeated fields of double values. This performs better than
+ * boxing into NSNumbers in NSArrays.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBDoubleArray : NSObject <NSCopying>
+/** The number of elements contained in the array. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty GPBDoubleArray.
+ **/
+ (instancetype)array;
+
+/**
+ * Creates and initializes a GPBDoubleArray with the single element given.
+ *
+ * @param value The value to be placed in the array.
+ *
+ * @return A newly instanced GPBDoubleArray with value in it.
+ **/
+ (instancetype)arrayWithValue:(double)value;
+
+/**
+ * Creates and initializes a GPBDoubleArray with the contents of the given
+ * array.
+ *
+ * @param array Array with the contents to be put into the new array.
+ *
+ * @return A newly instanced GPBDoubleArray with the contents of array.
+ **/
+ (instancetype)arrayWithValueArray:(GPBDoubleArray *)array;
+
+/**
+ * Creates and initializes a GPBDoubleArray with the given capacity.
+ *
+ * @param count The capacity needed for the array.
+ *
+ * @return A newly instanced GPBDoubleArray with a capacity of count.
+ **/
+ (instancetype)arrayWithCapacity:(NSUInteger)count;
+/**
+ * @return A newly initialized and empty GPBDoubleArray.
+ **/
- (instancetype)init NS_DESIGNATED_INITIALIZER;
-// Initializes the array, copying the values.
+
+/**
+ * Initializes the array, copying the given values.
+ *
+ * @param values An array with the values to put inside this array.
+ * @param count The number of elements to copy into the array.
+ *
+ * @return A newly initialized GPBDoubleArray with a copy of the values.
+ **/
- (instancetype)initWithValues:(const double [])values
count:(NSUInteger)count;
+
+/**
+ * Initializes the array, copying the given values.
+ *
+ * @param array An array with the values to put inside this array.
+ *
+ * @return A newly initialized GPBDoubleArray with a copy of the values.
+ **/
- (instancetype)initWithValueArray:(GPBDoubleArray *)array;
+
+/**
+ * Initializes the array with the given capacity.
+ *
+ * @param count The capacity needed for the array.
+ *
+ * @return A newly initialized GPBDoubleArray with a capacity of count.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)count;
+/**
+ * Gets the value at the given index.
+ *
+ * @param index The index of the value to get.
+ *
+ * @return The value at the given index.
+ **/
- (double)valueAtIndex:(NSUInteger)index;
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateValuesWithBlock:(void (^)(double value, NSUInteger idx, BOOL *stop))block;
+
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param opts Options to control the enumeration.
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
usingBlock:(void (^)(double value, NSUInteger idx, BOOL *stop))block;
+/**
+ * Adds a value to this array.
+ *
+ * @param value The value to add to this array.
+ **/
- (void)addValue:(double)value;
+
+/**
+ * Adds values to this array.
+ *
+ * @param values The values to add to this array.
+ * @param count The number of elements to add.
+ **/
- (void)addValues:(const double [])values count:(NSUInteger)count;
+
+/**
+ * Adds the values from the given array to this array.
+ *
+ * @param array The array containing the elements to add to this array.
+ **/
- (void)addValuesFromArray:(GPBDoubleArray *)array;
+/**
+ * Inserts a value into the given position.
+ *
+ * @param value The value to add to this array.
+ * @param index The index into which to insert the value.
+ **/
- (void)insertValue:(double)value atIndex:(NSUInteger)index;
+/**
+ * Replaces the value at the given index with the given value.
+ *
+ * @param index The index for which to replace the value.
+ * @param value The value to replace with.
+ **/
- (void)replaceValueAtIndex:(NSUInteger)index withValue:(double)value;
+/**
+ * Removes the value at the given index.
+ *
+ * @param index The index of the value to remove.
+ **/
- (void)removeValueAtIndex:(NSUInteger)index;
+
+/**
+ * Removes all the values from this array.
+ **/
- (void)removeAll;
+/**
+ * Exchanges the values between the given indexes.
+ *
+ * @param idx1 The index of the first element to exchange.
+ * @param idx2 The index of the second element to exchange.
+ **/
- (void)exchangeValueAtIndex:(NSUInteger)idx1
withValueAtIndex:(NSUInteger)idx2;
@@ -284,39 +1071,171 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Bool
+/**
+ * Class used for repeated fields of BOOL values. This performs better than
+ * boxing into NSNumbers in NSArrays.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBBoolArray : NSObject <NSCopying>
+/** The number of elements contained in the array. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty GPBBoolArray.
+ **/
+ (instancetype)array;
+
+/**
+ * Creates and initializes a GPBBoolArray with the single element given.
+ *
+ * @param value The value to be placed in the array.
+ *
+ * @return A newly instanced GPBBoolArray with value in it.
+ **/
+ (instancetype)arrayWithValue:(BOOL)value;
+
+/**
+ * Creates and initializes a GPBBoolArray with the contents of the given
+ * array.
+ *
+ * @param array Array with the contents to be put into the new array.
+ *
+ * @return A newly instanced GPBBoolArray with the contents of array.
+ **/
+ (instancetype)arrayWithValueArray:(GPBBoolArray *)array;
+
+/**
+ * Creates and initializes a GPBBoolArray with the given capacity.
+ *
+ * @param count The capacity needed for the array.
+ *
+ * @return A newly instanced GPBBoolArray with a capacity of count.
+ **/
+ (instancetype)arrayWithCapacity:(NSUInteger)count;
+/**
+ * @return A newly initialized and empty GPBBoolArray.
+ **/
- (instancetype)init NS_DESIGNATED_INITIALIZER;
-// Initializes the array, copying the values.
+
+/**
+ * Initializes the array, copying the given values.
+ *
+ * @param values An array with the values to put inside this array.
+ * @param count The number of elements to copy into the array.
+ *
+ * @return A newly initialized GPBBoolArray with a copy of the values.
+ **/
- (instancetype)initWithValues:(const BOOL [])values
count:(NSUInteger)count;
+
+/**
+ * Initializes the array, copying the given values.
+ *
+ * @param array An array with the values to put inside this array.
+ *
+ * @return A newly initialized GPBBoolArray with a copy of the values.
+ **/
- (instancetype)initWithValueArray:(GPBBoolArray *)array;
+
+/**
+ * Initializes the array with the given capacity.
+ *
+ * @param count The capacity needed for the array.
+ *
+ * @return A newly initialized GPBBoolArray with a capacity of count.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)count;
+/**
+ * Gets the value at the given index.
+ *
+ * @param index The index of the value to get.
+ *
+ * @return The value at the given index.
+ **/
- (BOOL)valueAtIndex:(NSUInteger)index;
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateValuesWithBlock:(void (^)(BOOL value, NSUInteger idx, BOOL *stop))block;
+
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param opts Options to control the enumeration.
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
usingBlock:(void (^)(BOOL value, NSUInteger idx, BOOL *stop))block;
+/**
+ * Adds a value to this array.
+ *
+ * @param value The value to add to this array.
+ **/
- (void)addValue:(BOOL)value;
+
+/**
+ * Adds values to this array.
+ *
+ * @param values The values to add to this array.
+ * @param count The number of elements to add.
+ **/
- (void)addValues:(const BOOL [])values count:(NSUInteger)count;
+
+/**
+ * Adds the values from the given array to this array.
+ *
+ * @param array The array containing the elements to add to this array.
+ **/
- (void)addValuesFromArray:(GPBBoolArray *)array;
+/**
+ * Inserts a value into the given position.
+ *
+ * @param value The value to add to this array.
+ * @param index The index into which to insert the value.
+ **/
- (void)insertValue:(BOOL)value atIndex:(NSUInteger)index;
+/**
+ * Replaces the value at the given index with the given value.
+ *
+ * @param index The index for which to replace the value.
+ * @param value The value to replace with.
+ **/
- (void)replaceValueAtIndex:(NSUInteger)index withValue:(BOOL)value;
+/**
+ * Removes the value at the given index.
+ *
+ * @param index The index of the value to remove.
+ **/
- (void)removeValueAtIndex:(NSUInteger)index;
+
+/**
+ * Removes all the values from this array.
+ **/
- (void)removeAll;
+/**
+ * Exchanges the values between the given indexes.
+ *
+ * @param idx1 The index of the first element to exchange.
+ * @param idx2 The index of the second element to exchange.
+ **/
- (void)exchangeValueAtIndex:(NSUInteger)idx1
withValueAtIndex:(NSUInteger)idx2;
@@ -324,27 +1243,108 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Enum
+/**
+ * This class is used for repeated fields of int32_t values. This performs
+ * better than boxing into NSNumbers in NSArrays.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBEnumArray : NSObject <NSCopying>
+/** The number of elements contained in the array. */
@property(nonatomic, readonly) NSUInteger count;
+/** The validation function to check if the enums are valid. */
@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+/**
+ * @return A newly instanced and empty GPBEnumArray.
+ **/
+ (instancetype)array;
+
+/**
+ * Creates and initializes a GPBEnumArray with the enum validation function
+ * given.
+ *
+ * @param func The enum validation function for the array.
+ *
+ * @return A newly instanced GPBEnumArray.
+ **/
+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+
+/**
+ * Creates and initializes a GPBEnumArray with the enum validation function
+ * given and the single raw value given.
+ *
+ * @param func The enum validation function for the array.
+ * @param value The raw value to add to this array.
+ *
+ * @return A newly instanced GPBEnumArray.
+ **/
+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValue:(int32_t)value;
+
+/**
+ * Creates and initializes a GPBEnumArray that adds the elements from the
+ * given array.
+ *
+ * @param array Array containing the values to add to the new array.
+ *
+ * @return A newly instanced GPBEnumArray.
+ **/
+ (instancetype)arrayWithValueArray:(GPBEnumArray *)array;
+
+/**
+ * Creates and initializes a GPBEnumArray with the given enum validation
+ * function and with the givencapacity.
+ *
+ * @param func The enum validation function for the array.
+ * @param count The capacity needed for the array.
+ *
+ * @return A newly instanced GPBEnumArray with a capacity of count.
+ **/
+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func
capacity:(NSUInteger)count;
+/**
+ * Initializes the array with the given enum validation function.
+ *
+ * @param func The enum validation function for the array.
+ *
+ * @return A newly initialized GPBEnumArray with a copy of the values.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
NS_DESIGNATED_INITIALIZER;
-// Initializes the array, copying the values.
+/**
+ * Initializes the array, copying the given values.
+ *
+ * @param func The enum validation function for the array.
+ * @param values An array with the values to put inside this array.
+ * @param count The number of elements to copy into the array.
+ *
+ * @return A newly initialized GPBEnumArray with a copy of the values.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValues:(const int32_t [])values
count:(NSUInteger)count;
+
+/**
+ * Initializes the array, copying the given values.
+ *
+ * @param array An array with the values to put inside this array.
+ *
+ * @return A newly initialized GPBEnumArray with a copy of the values.
+ **/
- (instancetype)initWithValueArray:(GPBEnumArray *)array;
+
+/**
+ * Initializes the array with the given capacity.
+ *
+ * @param func The enum validation function for the array.
+ * @param count The capacity needed for the array.
+ *
+ * @return A newly initialized GPBEnumArray with a capacity of count.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
capacity:(NSUInteger)count;
@@ -352,18 +1352,68 @@ NS_ASSUME_NONNULL_BEGIN
// valid enumerator as defined by validationFunc. If the actual value is
// desired, use "raw" version of the method.
+/**
+ * Gets the value at the given index.
+ *
+ * @param index The index of the value to get.
+ *
+ * @return The value at the given index.
+ **/
- (int32_t)valueAtIndex:(NSUInteger)index;
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param opts Options to control the enumeration.
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
// These methods bypass the validationFunc to provide access to values that were not
// known at the time the binary was compiled.
+/**
+ * Gets the raw enum value at the given index.
+ *
+ * @param index The index of the raw enum value to get.
+ *
+ * @return The raw enum value at the given index.
+ **/
- (int32_t)rawValueAtIndex:(NSUInteger)index;
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateRawValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+
+/**
+ * Enumerates the values on this array with the given block.
+ *
+ * @param opts Options to control the enumeration.
+ * @param block The block to enumerate with.
+ * **value**: The current value being enumerated.
+ * **idx**: The index of the current value.
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts
usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
@@ -372,29 +1422,114 @@ NS_ASSUME_NONNULL_BEGIN
// to the default value. Use the rawValue methods below to assign non enumerator
// values.
+/**
+ * Adds a value to this array.
+ *
+ * @param value The value to add to this array.
+ **/
- (void)addValue:(int32_t)value;
+
+/**
+ * Adds values to this array.
+ *
+ * @param values The values to add to this array.
+ * @param count The number of elements to add.
+ **/
- (void)addValues:(const int32_t [])values count:(NSUInteger)count;
+
+/**
+ * Inserts a value into the given position.
+ *
+ * @param value The value to add to this array.
+ * @param index The index into which to insert the value.
+ **/
- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index;
+/**
+ * Replaces the value at the given index with the given value.
+ *
+ * @param index The index for which to replace the value.
+ * @param value The value to replace with.
+ **/
- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value;
// These methods bypass the validationFunc to provide setting of values that were not
// known at the time the binary was compiled.
+/**
+ * Adds a raw enum value to this array.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param value The raw enum value to add to the array.
+ **/
- (void)addRawValue:(int32_t)value;
+
+/**
+ * Adds raw enum values to this array.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param array Array containing the raw enum values to add to this array.
+ **/
- (void)addRawValuesFromArray:(GPBEnumArray *)array;
+
+/**
+ * Adds raw enum values to this array.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param values Array containing the raw enum values to add to this array.
+ * @param count The number of raw values to add.
+ **/
- (void)addRawValues:(const int32_t [])values count:(NSUInteger)count;
+/**
+ * Inserts a raw enum value at the given index.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param value Raw enum value to add.
+ * @param index The index into which to insert the value.
+ **/
- (void)insertRawValue:(int32_t)value atIndex:(NSUInteger)index;
+/**
+ * Replaces the raw enum value at the given index with the given value.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param index The index for which to replace the value.
+ * @param value The raw enum value to replace with.
+ **/
- (void)replaceValueAtIndex:(NSUInteger)index withRawValue:(int32_t)value;
// No validation applies to these methods.
+/**
+ * Removes the value at the given index.
+ *
+ * @param index The index of the value to remove.
+ **/
- (void)removeValueAtIndex:(NSUInteger)index;
+
+/**
+ * Removes all the values from this array.
+ **/
- (void)removeAll;
+/**
+ * Exchanges the values between the given indexes.
+ *
+ * @param idx1 The index of the first element to exchange.
+ * @param idx2 The index of the second element to exchange.
+ **/
- (void)exchangeValueAtIndex:(NSUInteger)idx1
withValueAtIndex:(NSUInteger)idx2;
@@ -421,20 +1556,82 @@ NS_ASSUME_NONNULL_END
//%PDDM-DEFINE ARRAY_INTERFACE_SIMPLE(NAME, TYPE)
//%#pragma mark - NAME
//%
+//%/**
+//% * Class used for repeated fields of ##TYPE## values. This performs better than
+//% * boxing into NSNumbers in NSArrays.
+//% *
+//% * @note This class is not meant to be subclassed.
+//% **/
//%@interface GPB##NAME##Array : NSObject <NSCopying>
//%
+//%/** The number of elements contained in the array. */
//%@property(nonatomic, readonly) NSUInteger count;
//%
+//%/**
+//% * @return A newly instanced and empty GPB##NAME##Array.
+//% **/
//%+ (instancetype)array;
+//%
+//%/**
+//% * Creates and initializes a GPB##NAME##Array with the single element given.
+//% *
+//% * @param value The value to be placed in the array.
+//% *
+//% * @return A newly instanced GPB##NAME##Array with value in it.
+//% **/
//%+ (instancetype)arrayWithValue:(TYPE)value;
+//%
+//%/**
+//% * Creates and initializes a GPB##NAME##Array with the contents of the given
+//% * array.
+//% *
+//% * @param array Array with the contents to be put into the new array.
+//% *
+//% * @return A newly instanced GPB##NAME##Array with the contents of array.
+//% **/
//%+ (instancetype)arrayWithValueArray:(GPB##NAME##Array *)array;
+//%
+//%/**
+//% * Creates and initializes a GPB##NAME##Array with the given capacity.
+//% *
+//% * @param count The capacity needed for the array.
+//% *
+//% * @return A newly instanced GPB##NAME##Array with a capacity of count.
+//% **/
//%+ (instancetype)arrayWithCapacity:(NSUInteger)count;
//%
+//%/**
+//% * @return A newly initialized and empty GPB##NAME##Array.
+//% **/
//%- (instancetype)init NS_DESIGNATED_INITIALIZER;
-//%// Initializes the array, copying the values.
+//%
+//%/**
+//% * Initializes the array, copying the given values.
+//% *
+//% * @param values An array with the values to put inside this array.
+//% * @param count The number of elements to copy into the array.
+//% *
+//% * @return A newly initialized GPB##NAME##Array with a copy of the values.
+//% **/
//%- (instancetype)initWithValues:(const TYPE [])values
//% count:(NSUInteger)count;
+//%
+//%/**
+//% * Initializes the array, copying the given values.
+//% *
+//% * @param array An array with the values to put inside this array.
+//% *
+//% * @return A newly initialized GPB##NAME##Array with a copy of the values.
+//% **/
//%- (instancetype)initWithValueArray:(GPB##NAME##Array *)array;
+//%
+//%/**
+//% * Initializes the array with the given capacity.
+//% *
+//% * @param count The capacity needed for the array.
+//% *
+//% * @return A newly initialized GPB##NAME##Array with a capacity of count.
+//% **/
//%- (instancetype)initWithCapacity:(NSUInteger)count;
//%
//%ARRAY_IMMUTABLE_INTERFACE(NAME, TYPE, Basic)
@@ -451,27 +1648,108 @@ NS_ASSUME_NONNULL_END
//%PDDM-DEFINE ARRAY_INTERFACE_ENUM(NAME, TYPE)
//%#pragma mark - NAME
//%
+//%/**
+//% * This class is used for repeated fields of ##TYPE## values. This performs
+//% * better than boxing into NSNumbers in NSArrays.
+//% *
+//% * @note This class is not meant to be subclassed.
+//% **/
//%@interface GPB##NAME##Array : NSObject <NSCopying>
//%
+//%/** The number of elements contained in the array. */
//%@property(nonatomic, readonly) NSUInteger count;
+//%/** The validation function to check if the enums are valid. */
//%@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
//%
+//%/**
+//% * @return A newly instanced and empty GPB##NAME##Array.
+//% **/
//%+ (instancetype)array;
+//%
+//%/**
+//% * Creates and initializes a GPB##NAME##Array with the enum validation function
+//% * given.
+//% *
+//% * @param func The enum validation function for the array.
+//% *
+//% * @return A newly instanced GPB##NAME##Array.
+//% **/
//%+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+//%
+//%/**
+//% * Creates and initializes a GPB##NAME##Array with the enum validation function
+//% * given and the single raw value given.
+//% *
+//% * @param func The enum validation function for the array.
+//% * @param value The raw value to add to this array.
+//% *
+//% * @return A newly instanced GPB##NAME##Array.
+//% **/
//%+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func
//% rawValue:(TYPE)value;
+//%
+//%/**
+//% * Creates and initializes a GPB##NAME##Array that adds the elements from the
+//% * given array.
+//% *
+//% * @param array Array containing the values to add to the new array.
+//% *
+//% * @return A newly instanced GPB##NAME##Array.
+//% **/
//%+ (instancetype)arrayWithValueArray:(GPB##NAME##Array *)array;
+//%
+//%/**
+//% * Creates and initializes a GPB##NAME##Array with the given enum validation
+//% * function and with the givencapacity.
+//% *
+//% * @param func The enum validation function for the array.
+//% * @param count The capacity needed for the array.
+//% *
+//% * @return A newly instanced GPB##NAME##Array with a capacity of count.
+//% **/
//%+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func
//% capacity:(NSUInteger)count;
//%
+//%/**
+//% * Initializes the array with the given enum validation function.
+//% *
+//% * @param func The enum validation function for the array.
+//% *
+//% * @return A newly initialized GPB##NAME##Array with a copy of the values.
+//% **/
//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
//% NS_DESIGNATED_INITIALIZER;
//%
-//%// Initializes the array, copying the values.
+//%/**
+//% * Initializes the array, copying the given values.
+//% *
+//% * @param func The enum validation function for the array.
+//% * @param values An array with the values to put inside this array.
+//% * @param count The number of elements to copy into the array.
+//% *
+//% * @return A newly initialized GPB##NAME##Array with a copy of the values.
+//% **/
//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
//% rawValues:(const TYPE [])values
//% count:(NSUInteger)count;
+//%
+//%/**
+//% * Initializes the array, copying the given values.
+//% *
+//% * @param array An array with the values to put inside this array.
+//% *
+//% * @return A newly initialized GPB##NAME##Array with a copy of the values.
+//% **/
//%- (instancetype)initWithValueArray:(GPB##NAME##Array *)array;
+//%
+//%/**
+//% * Initializes the array with the given capacity.
+//% *
+//% * @param func The enum validation function for the array.
+//% * @param count The capacity needed for the array.
+//% *
+//% * @return A newly initialized GPB##NAME##Array with a capacity of count.
+//% **/
//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
//% capacity:(NSUInteger)count;
//%
@@ -484,9 +1762,34 @@ NS_ASSUME_NONNULL_END
//%// These methods bypass the validationFunc to provide access to values that were not
//%// known at the time the binary was compiled.
//%
+//%/**
+//% * Gets the raw enum value at the given index.
+//% *
+//% * @param index The index of the raw enum value to get.
+//% *
+//% * @return The raw enum value at the given index.
+//% **/
//%- (TYPE)rawValueAtIndex:(NSUInteger)index;
//%
+//%/**
+//% * Enumerates the values on this array with the given block.
+//% *
+//% * @param block The block to enumerate with.
+//% * **value**: The current value being enumerated.
+//% * **idx**: The index of the current value.
+//% * **stop**: A pointer to a boolean that when set stops the enumeration.
+//% **/
//%- (void)enumerateRawValuesWithBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block;
+//%
+//%/**
+//% * Enumerates the values on this array with the given block.
+//% *
+//% * @param opts Options to control the enumeration.
+//% * @param block The block to enumerate with.
+//% * **value**: The current value being enumerated.
+//% * **idx**: The index of the current value.
+//% * **stop**: A pointer to a boolean that when set stops the enumeration.
+//% **/
//%- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts
//% usingBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block;
//%
@@ -501,23 +1804,88 @@ NS_ASSUME_NONNULL_END
//%
//%PDDM-DEFINE ARRAY_IMMUTABLE_INTERFACE(NAME, TYPE, HELPER_NAME)
+//%/**
+//% * Gets the value at the given index.
+//% *
+//% * @param index The index of the value to get.
+//% *
+//% * @return The value at the given index.
+//% **/
//%- (TYPE)valueAtIndex:(NSUInteger)index;
//%
+//%/**
+//% * Enumerates the values on this array with the given block.
+//% *
+//% * @param block The block to enumerate with.
+//% * **value**: The current value being enumerated.
+//% * **idx**: The index of the current value.
+//% * **stop**: A pointer to a boolean that when set stops the enumeration.
+//% **/
//%- (void)enumerateValuesWithBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block;
+//%
+//%/**
+//% * Enumerates the values on this array with the given block.
+//% *
+//% * @param opts Options to control the enumeration.
+//% * @param block The block to enumerate with.
+//% * **value**: The current value being enumerated.
+//% * **idx**: The index of the current value.
+//% * **stop**: A pointer to a boolean that when set stops the enumeration.
+//% **/
//%- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
//% usingBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block;
//%PDDM-DEFINE ARRAY_MUTABLE_INTERFACE(NAME, TYPE, HELPER_NAME)
+//%/**
+//% * Adds a value to this array.
+//% *
+//% * @param value The value to add to this array.
+//% **/
//%- (void)addValue:(TYPE)value;
+//%
+//%/**
+//% * Adds values to this array.
+//% *
+//% * @param values The values to add to this array.
+//% * @param count The number of elements to add.
+//% **/
//%- (void)addValues:(const TYPE [])values count:(NSUInteger)count;
+//%
//%ARRAY_EXTRA_MUTABLE_METHODS1_##HELPER_NAME(NAME, TYPE)
+//%/**
+//% * Inserts a value into the given position.
+//% *
+//% * @param value The value to add to this array.
+//% * @param index The index into which to insert the value.
+//% **/
//%- (void)insertValue:(TYPE)value atIndex:(NSUInteger)index;
//%
+//%/**
+//% * Replaces the value at the given index with the given value.
+//% *
+//% * @param index The index for which to replace the value.
+//% * @param value The value to replace with.
+//% **/
//%- (void)replaceValueAtIndex:(NSUInteger)index withValue:(TYPE)value;
//%ARRAY_EXTRA_MUTABLE_METHODS2_##HELPER_NAME(NAME, TYPE)
+//%/**
+//% * Removes the value at the given index.
+//% *
+//% * @param index The index of the value to remove.
+//% **/
//%- (void)removeValueAtIndex:(NSUInteger)index;
+//%
+//%/**
+//% * Removes all the values from this array.
+//% **/
//%- (void)removeAll;
//%
+//%/**
+//% * Exchanges the values between the given indexes.
+//% *
+//% * @param idx1 The index of the first element to exchange.
+//% * @param idx2 The index of the second element to exchange.
+//% **/
//%- (void)exchangeValueAtIndex:(NSUInteger)idx1
//% withValueAtIndex:(NSUInteger)idx2;
@@ -526,6 +1894,11 @@ NS_ASSUME_NONNULL_END
//
//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS1_Basic(NAME, TYPE)
+//%/**
+//% * Adds the values from the given array to this array.
+//% *
+//% * @param array The array containing the elements to add to this array.
+//% **/
//%- (void)addValuesFromArray:(GPB##NAME##Array *)array;
//%
//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS2_Basic(NAME, TYPE)
@@ -537,12 +1910,57 @@ NS_ASSUME_NONNULL_END
//%// These methods bypass the validationFunc to provide setting of values that were not
//%// known at the time the binary was compiled.
//%
+//%/**
+//% * Adds a raw enum value to this array.
+//% *
+//% * @note This method bypass the validationFunc to enable the setting of values that
+//% * were not known at the time the binary was compiled.
+//% *
+//% * @param value The raw enum value to add to the array.
+//% **/
//%- (void)addRawValue:(TYPE)value;
+//%
+//%/**
+//% * Adds raw enum values to this array.
+//% *
+//% * @note This method bypass the validationFunc to enable the setting of values that
+//% * were not known at the time the binary was compiled.
+//% *
+//% * @param array Array containing the raw enum values to add to this array.
+//% **/
//%- (void)addRawValuesFromArray:(GPB##NAME##Array *)array;
+//%
+//%/**
+//% * Adds raw enum values to this array.
+//% *
+//% * @note This method bypass the validationFunc to enable the setting of values that
+//% * were not known at the time the binary was compiled.
+//% *
+//% * @param values Array containing the raw enum values to add to this array.
+//% * @param count The number of raw values to add.
+//% **/
//%- (void)addRawValues:(const TYPE [])values count:(NSUInteger)count;
//%
+//%/**
+//% * Inserts a raw enum value at the given index.
+//% *
+//% * @note This method bypass the validationFunc to enable the setting of values that
+//% * were not known at the time the binary was compiled.
+//% *
+//% * @param value Raw enum value to add.
+//% * @param index The index into which to insert the value.
+//% **/
//%- (void)insertRawValue:(TYPE)value atIndex:(NSUInteger)index;
//%
+//%/**
+//% * Replaces the raw enum value at the given index with the given value.
+//% *
+//% * @note This method bypass the validationFunc to enable the setting of values that
+//% * were not known at the time the binary was compiled.
+//% *
+//% * @param index The index for which to replace the value.
+//% * @param value The raw enum value to replace with.
+//% **/
//%- (void)replaceValueAtIndex:(NSUInteger)index withRawValue:(TYPE)value;
//%
//%// No validation applies to these methods.
diff --git a/objectivec/GPBArray.m b/objectivec/GPBArray.m
index 64869bbb..ae57747d 100644
--- a/objectivec/GPBArray.m
+++ b/objectivec/GPBArray.m
@@ -195,7 +195,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) {
//%}
//%
//%- (void)enumerate##ACCESSOR_NAME##ValuesWithBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block {
-//% [self enumerate##ACCESSOR_NAME##ValuesWithOptions:0 usingBlock:block];
+//% [self enumerate##ACCESSOR_NAME##ValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
//%}
//%
//%- (void)enumerate##ACCESSOR_NAME##ValuesWithOptions:(NSEnumerationOptions)opts
@@ -406,7 +406,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) {
}
- (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block {
- [self enumerateValuesWithOptions:0 usingBlock:block];
+ [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
}
- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
@@ -654,7 +654,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) {
}
- (void)enumerateValuesWithBlock:(void (^)(uint32_t value, NSUInteger idx, BOOL *stop))block {
- [self enumerateValuesWithOptions:0 usingBlock:block];
+ [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
}
- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
@@ -902,7 +902,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) {
}
- (void)enumerateValuesWithBlock:(void (^)(int64_t value, NSUInteger idx, BOOL *stop))block {
- [self enumerateValuesWithOptions:0 usingBlock:block];
+ [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
}
- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
@@ -1150,7 +1150,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) {
}
- (void)enumerateValuesWithBlock:(void (^)(uint64_t value, NSUInteger idx, BOOL *stop))block {
- [self enumerateValuesWithOptions:0 usingBlock:block];
+ [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
}
- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
@@ -1398,7 +1398,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) {
}
- (void)enumerateValuesWithBlock:(void (^)(float value, NSUInteger idx, BOOL *stop))block {
- [self enumerateValuesWithOptions:0 usingBlock:block];
+ [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
}
- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
@@ -1646,7 +1646,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) {
}
- (void)enumerateValuesWithBlock:(void (^)(double value, NSUInteger idx, BOOL *stop))block {
- [self enumerateValuesWithOptions:0 usingBlock:block];
+ [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
}
- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
@@ -1894,7 +1894,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) {
}
- (void)enumerateValuesWithBlock:(void (^)(BOOL value, NSUInteger idx, BOOL *stop))block {
- [self enumerateValuesWithOptions:0 usingBlock:block];
+ [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
}
- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
@@ -2166,7 +2166,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) {
}
- (void)enumerateRawValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block {
- [self enumerateRawValuesWithOptions:0 usingBlock:block];
+ [self enumerateRawValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
}
- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts
@@ -2218,7 +2218,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) {
}
- (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block {
- [self enumerateValuesWithOptions:0 usingBlock:block];
+ [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
}
- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
diff --git a/objectivec/GPBBootstrap.h b/objectivec/GPBBootstrap.h
index 4db08e80..7dc943d4 100644
--- a/objectivec/GPBBootstrap.h
+++ b/objectivec/GPBBootstrap.h
@@ -28,11 +28,13 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// The Objective C runtime has complete enough info that most protos don’t end
-// up using this, so leaving it on is no cost or very little cost. If you
-// happen to see it causing bloat, this is the way to disable it. If you do
-// need to disable it, try only disabling it for Release builds as having
-// full TextFormat can be useful for debugging.
+/**
+ * The Objective C runtime has complete enough info that most protos don’t end
+ * up using this, so leaving it on is no cost or very little cost. If you
+ * happen to see it causing bloat, this is the way to disable it. If you do
+ * need to disable it, try only disabling it for Release builds as having
+ * full TextFormat can be useful for debugging.
+ **/
#ifndef GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
#define GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS 0
#endif
@@ -42,6 +44,7 @@
#if !__has_feature(objc_fixed_enum)
#error All supported Xcode versions should support objc_fixed_enum.
#endif
+
// If the headers are imported into Objective-C++, we can run into an issue
// where the defintion of NS_ENUM (really CF_ENUM) changes based on the C++
// standard that is in effect. If it isn't C++11 or higher, the definition
@@ -53,19 +56,29 @@
#else
#define GPB_ENUM(X) NS_ENUM(int32_t, X)
#endif
-// GPB_ENUM_FWD_DECLARE is used for forward declaring enums, ex:
-// GPB_ENUM_FWD_DECLARE(Foo_Enum)
-// @property (nonatomic) Foo_Enum value;
+
+/**
+ * GPB_ENUM_FWD_DECLARE is used for forward declaring enums, for example:
+ *
+ * ```
+ * GPB_ENUM_FWD_DECLARE(Foo_Enum)
+ * @property (nonatomic) Foo_Enum value;
+ * ```
+ **/
#define GPB_ENUM_FWD_DECLARE(X) enum X : int32_t
-// Based upon CF_INLINE. Forces inlining in release.
+/**
+ * Based upon CF_INLINE. Forces inlining in non DEBUG builds.
+ **/
#if !defined(DEBUG)
#define GPB_INLINE static __inline__ __attribute__((always_inline))
#else
#define GPB_INLINE static __inline__
#endif
-// For use in public headers that might need to deal with ARC.
+/**
+ * For use in public headers that might need to deal with ARC.
+ **/
#ifndef GPB_UNSAFE_UNRETAINED
#if __has_feature(objc_arc)
#define GPB_UNSAFE_UNRETAINED __unsafe_unretained
@@ -76,10 +89,14 @@
// If property name starts with init we need to annotate it to get past ARC.
// http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
+//
+// Meant to be used internally by generated code.
#define GPB_METHOD_FAMILY_NONE __attribute__((objc_method_family(none)))
// The protoc-gen-objc version which works with the current version of the
// generated Objective C sources. In general we don't want to change the
// runtime interfaces (or this version) as it means everything has to be
// regenerated.
-#define GOOGLE_PROTOBUF_OBJC_GEN_VERSION 30001
+//
+// Meant to be used internally by generated code.
+#define GOOGLE_PROTOBUF_OBJC_GEN_VERSION 30002
diff --git a/objectivec/GPBCodedInputStream.h b/objectivec/GPBCodedInputStream.h
index df9d97ba..de27b186 100644
--- a/objectivec/GPBCodedInputStream.h
+++ b/objectivec/GPBCodedInputStream.h
@@ -37,125 +37,194 @@ NS_ASSUME_NONNULL_BEGIN
CF_EXTERN_C_BEGIN
-/// GPBCodedInputStream exception name. Exceptions raised from
-/// GPBCodedInputStream contain an underlying error in the userInfo dictionary
-/// under the GPBCodedInputStreamUnderlyingErrorKey key.
+/**
+ * @c GPBCodedInputStream exception name. Exceptions raised from
+ * @c GPBCodedInputStream contain an underlying error in the userInfo dictionary
+ * under the GPBCodedInputStreamUnderlyingErrorKey key.
+ **/
extern NSString *const GPBCodedInputStreamException;
-/// The key under which the underlying NSError from the exception is stored.
+/** The key under which the underlying NSError from the exception is stored. */
extern NSString *const GPBCodedInputStreamUnderlyingErrorKey;
-/// NSError domain used for GPBCodedInputStream errors.
+/** NSError domain used for @c GPBCodedInputStream errors. */
extern NSString *const GPBCodedInputStreamErrorDomain;
-/// Error code for NSError with GPBCodedInputStreamErrorDomain.
+/**
+ * Error code for NSError with @c GPBCodedInputStreamErrorDomain.
+ **/
typedef NS_ENUM(NSInteger, GPBCodedInputStreamErrorCode) {
- /// The size does not fit in the remaining bytes to be read.
+ /** The size does not fit in the remaining bytes to be read. */
GPBCodedInputStreamErrorInvalidSize = -100,
- /// Attempted to read beyond the subsection limit.
+ /** Attempted to read beyond the subsection limit. */
GPBCodedInputStreamErrorSubsectionLimitReached = -101,
- /// The requested subsection limit is invalid.
+ /** The requested subsection limit is invalid. */
GPBCodedInputStreamErrorInvalidSubsectionLimit = -102,
- /// Invalid tag read.
+ /** Invalid tag read. */
GPBCodedInputStreamErrorInvalidTag = -103,
- /// Invalid UTF-8 character in a string.
+ /** Invalid UTF-8 character in a string. */
GPBCodedInputStreamErrorInvalidUTF8 = -104,
- /// Invalid VarInt read.
+ /** Invalid VarInt read. */
GPBCodedInputStreamErrorInvalidVarInt = -105,
- /// The maximum recursion depth of messages was exceeded.
+ /** The maximum recursion depth of messages was exceeded. */
GPBCodedInputStreamErrorRecursionDepthExceeded = -106,
};
CF_EXTERN_C_END
-/// Reads and decodes protocol message fields.
-///
-/// The common uses of protocol buffers shouldn't need to use this class.
-/// @c GPBMessage's provide a @c +parseFromData:error: and @c
-/// +parseFromData:extensionRegistry:error: method that will decode a
-/// message for you.
-///
-/// @note Subclassing of GPBCodedInputStream is NOT supported.
+/**
+ * Reads and decodes protocol message fields.
+ *
+ * The common uses of protocol buffers shouldn't need to use this class.
+ * @c GPBMessage's provide a @c +parseFromData:error: and
+ * @c +parseFromData:extensionRegistry:error: method that will decode a
+ * message for you.
+ *
+ * @note Subclassing of @c GPBCodedInputStream is NOT supported.
+ **/
@interface GPBCodedInputStream : NSObject
-/// Creates a new stream wrapping some data.
+/**
+ * Creates a new stream wrapping some data.
+ *
+ * @param data The data to wrap inside the stream.
+ *
+ * @return A newly instanced GPBCodedInputStream.
+ **/
+ (instancetype)streamWithData:(NSData *)data;
-/// Initializes a stream wrapping some data.
+/**
+ * Initializes a stream wrapping some data.
+ *
+ * @param data The data to wrap inside the stream.
+ *
+ * @return A newly initialized GPBCodedInputStream.
+ **/
- (instancetype)initWithData:(NSData *)data;
-/// Attempt to read a field tag, returning zero if we have reached EOF.
-/// Protocol message parsers use this to read tags, since a protocol message
-/// may legally end wherever a tag occurs, and zero is not a valid tag number.
+/**
+ * Attempts to read a field tag, returning zero if we have reached EOF.
+ * Protocol message parsers use this to read tags, since a protocol message
+ * may legally end wherever a tag occurs, and zero is not a valid tag number.
+ *
+ * @return The field tag, or zero if EOF was reached.
+ **/
- (int32_t)readTag;
-/// Read and return a double.
+/**
+ * @return A double read from the stream.
+ **/
- (double)readDouble;
-/// Read and return a float.
+/**
+ * @return A float read from the stream.
+ **/
- (float)readFloat;
-/// Read and return a uint64.
+/**
+ * @return A uint64 read from the stream.
+ **/
- (uint64_t)readUInt64;
-/// Read and return a uint32.
+/**
+ * @return A uint32 read from the stream.
+ **/
- (uint32_t)readUInt32;
-/// Read and return an int64.
+/**
+ * @return An int64 read from the stream.
+ **/
- (int64_t)readInt64;
-/// Read and return an int32.
+/**
+ * @return An int32 read from the stream.
+ **/
- (int32_t)readInt32;
-/// Read and return a fixed64.
+/**
+ * @return A fixed64 read from the stream.
+ **/
- (uint64_t)readFixed64;
-/// Read and return a fixed32.
+/**
+ * @return A fixed32 read from the stream.
+ **/
- (uint32_t)readFixed32;
-/// Read and return an enum (int).
+/**
+ * @return An enum read from the stream.
+ **/
- (int32_t)readEnum;
-/// Read and return a sfixed32.
+/**
+ * @return A sfixed32 read from the stream.
+ **/
- (int32_t)readSFixed32;
-/// Read and return a sfixed64.
+/**
+ * @return A fixed64 read from the stream.
+ **/
- (int64_t)readSFixed64;
-/// Read and return a sint32.
+/**
+ * @return A sint32 read from the stream.
+ **/
- (int32_t)readSInt32;
-/// Read and return a sint64.
+/**
+ * @return A sint64 read from the stream.
+ **/
- (int64_t)readSInt64;
-/// Read and return a boolean.
+/**
+ * @return A boolean read from the stream.
+ **/
- (BOOL)readBool;
-/// Read and return a string.
+/**
+ * @return A string read from the stream.
+ **/
- (NSString *)readString;
-/// Read and return length delimited data.
+/**
+ * @return Data read from the stream.
+ **/
- (NSData *)readBytes;
-/// Read an embedded message field value from the stream.
-///
-/// @param message The message to set fields on as they are read.
-/// @param extensionRegistry An optional extension registry to use to lookup
-/// extensions for @c message.
+/**
+ * Read an embedded message field value from the stream.
+ *
+ * @param message The message to set fields on as they are read.
+ * @param extensionRegistry An optional extension registry to use to lookup
+ * extensions for message.
+ **/
- (void)readMessage:(GPBMessage *)message
extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry;
-/// Reads and discards a single field, given its tag value.
-///
-/// @param tag The tag number of the field to skip.
-///
-/// @return NO if the tag is an endgroup tag (in which case nothing is skipped),
-/// YES in all other cases.
+/**
+ * Reads and discards a single field, given its tag value.
+ *
+ * @param tag The tag number of the field to skip.
+ *
+ * @return NO if the tag is an endgroup tag (in which case nothing is skipped),
+ * YES in all other cases.
+ **/
- (BOOL)skipField:(int32_t)tag;
-/// Reads and discards an entire message. This will read either until EOF
-/// or until an endgroup tag, whichever comes first.
+/**
+ * Reads and discards an entire message. This will read either until EOF or
+ * until an endgroup tag, whichever comes first.
+ **/
- (void)skipMessage;
-/// Check to see if the logical end of the stream has been reached.
-///
-/// This can return NO when there is no more data, but the current parsing
-/// expected more data.
+/**
+ * Check to see if the logical end of the stream has been reached.
+ *
+ * @note This can return NO when there is no more data, but the current parsing
+ * expected more data.
+ *
+ * @return YES if the logical end of the stream has been reached, NO otherwise.
+ **/
- (BOOL)isAtEnd;
-/// The offset into the stream.
+/**
+ * @return The offset into the stream.
+ **/
- (size_t)position;
-/// Verifies that the last call to @c -readTag returned the given tag value.
-/// This is used to verify that a nested group ended with the correct end tag.
-/// Throws @c NSParseErrorException if value does not match the last tag.
-///
-/// @param expected The tag that was expected.
+/**
+ * Verifies that the last call to -readTag returned the given tag value. This
+ * is used to verify that a nested group ended with the correct end tag.
+ *
+ * @exception NSParseErrorException If the value does not match the last tag.
+ *
+ * @param expected The tag that was expected.
+ **/
- (void)checkLastTagWas:(int32_t)expected;
@end
diff --git a/objectivec/GPBCodedOutputStream.h b/objectivec/GPBCodedOutputStream.h
index 8272880d..d6fff3db 100644
--- a/objectivec/GPBCodedOutputStream.h
+++ b/objectivec/GPBCodedOutputStream.h
@@ -46,63 +46,122 @@
NS_ASSUME_NONNULL_BEGIN
-/// Writes out protocol message fields.
-///
-/// The common uses of protocol buffers shouldn't need to use this class.
-/// @c GPBMessage's provide a @c -data method that will serialize the message
-/// for you.
-///
-/// @note Subclassing of GPBCodedOutputStream is NOT supported.
+/**
+ * Writes out protocol message fields.
+ *
+ * The common uses of protocol buffers shouldn't need to use this class.
+ * GPBMessage's provide a -data method that will serialize the message for you.
+ *
+ * @note Subclassing of GPBCodedOutputStream is NOT supported.
+ **/
@interface GPBCodedOutputStream : NSObject
-/// Creates a stream to fill in the given data. Data must be sized to fit or
-/// an error will be raised when out of space.
+/**
+ * Creates a stream to fill in the given data. Data must be sized to fit or
+ * an error will be raised when out of space.
+ *
+ * @param data The data where the stream will be written to.
+ *
+ * @return A newly instanced GPBCodedOutputStream.
+ **/
+ (instancetype)streamWithData:(NSMutableData *)data;
-/// Creates a stream to write into the given @c NSOutputStream.
+/**
+ * Creates a stream to write into the given NSOutputStream.
+ *
+ * @param output The output stream where the stream will be written to.
+ *
+ * @return A newly instanced GPBCodedOutputStream.
+ **/
+ (instancetype)streamWithOutputStream:(NSOutputStream *)output;
-/// Initializes a stream to fill in the given data. Data must be sized to fit
-/// or an error will be raised when out of space.
+/**
+ * Initializes a stream to fill in the given data. Data must be sized to fit
+ * or an error will be raised when out of space.
+ *
+ * @param data The data where the stream will be written to.
+ *
+ * @return A newly initialized GPBCodedOutputStream.
+ **/
- (instancetype)initWithData:(NSMutableData *)data;
-/// Initializes a stream to write into the given @c NSOutputStream.
+/**
+ * Initializes a stream to write into the given @c NSOutputStream.
+ *
+ * @param output The output stream where the stream will be written to.
+ *
+ * @return A newly initialized GPBCodedOutputStream.
+ **/
- (instancetype)initWithOutputStream:(NSOutputStream *)output;
-/// Flush any buffered data out.
+/**
+ * Flush any buffered data out.
+ **/
- (void)flush;
-/// Write the raw byte out.
+/**
+ * Write the raw byte out.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeRawByte:(uint8_t)value;
-/// Write the tag for the given field number and wire format.
-///
-/// @param fieldNumber The field number.
-/// @param format The wire format the data for the field will be in.
+/**
+ * Write the tag for the given field number and wire format.
+ *
+ * @param fieldNumber The field number.
+ * @param format The wire format the data for the field will be in.
+ **/
- (void)writeTag:(uint32_t)fieldNumber format:(GPBWireFormat)format;
-/// Write a 32bit value out in little endian format.
+/**
+ * Write a 32bit value out in little endian format.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeRawLittleEndian32:(int32_t)value;
-/// Write a 64bit value out in little endian format.
+/**
+ * Write a 64bit value out in little endian format.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeRawLittleEndian64:(int64_t)value;
-/// Write a 32bit value out in varint format.
+/**
+ * Write a 32bit value out in varint format.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeRawVarint32:(int32_t)value;
-/// Write a 64bit value out in varint format.
+/**
+ * Write a 64bit value out in varint format.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeRawVarint64:(int64_t)value;
-/// Write a size_t out as a 32bit varint value.
-///
-/// @note This will truncate 64 bit values to 32.
+/**
+ * Write a size_t out as a 32bit varint value.
+ *
+ * @note This will truncate 64 bit values to 32.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeRawVarintSizeTAs32:(size_t)value;
-/// Writes the contents of an @c NSData out.
+/**
+ * Writes the contents of an NSData out.
+ *
+ * @param data The data to write out.
+ **/
- (void)writeRawData:(NSData *)data;
-/// Writes out the given data.
-///
-/// @param data The data blob to write out.
-/// @param offset The offset into the blob to start writing out.
-/// @param length The number of bytes from the blob to write out.
+/**
+ * Writes out the given data.
+ *
+ * @param data The data blob to write out.
+ * @param offset The offset into the blob to start writing out.
+ * @param length The number of bytes from the blob to write out.
+ **/
- (void)writeRawPtr:(const void *)data
offset:(size_t)offset
length:(size_t)length;
@@ -110,179 +169,471 @@ NS_ASSUME_NONNULL_BEGIN
//%PDDM-EXPAND _WRITE_DECLS()
// This block of code is generated, do not edit it directly.
-/// Write a double for the given field number.
+/**
+ * Write a double for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeDouble:(int32_t)fieldNumber value:(double)value;
-/// Write a packed array of double for the given field number.
+/**
+ * Write a packed array of double for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ * @param tag The tag assigned to the values.
+ **/
- (void)writeDoubleArray:(int32_t)fieldNumber
values:(GPBDoubleArray *)values
tag:(uint32_t)tag;
-/// Write a double without any tag.
+/**
+ * Write a double without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeDoubleNoTag:(double)value;
-/// Write a float for the given field number.
+/**
+ * Write a float for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeFloat:(int32_t)fieldNumber value:(float)value;
-/// Write a packed array of float for the given field number.
+/**
+ * Write a packed array of float for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ * @param tag The tag assigned to the values.
+ **/
- (void)writeFloatArray:(int32_t)fieldNumber
values:(GPBFloatArray *)values
tag:(uint32_t)tag;
-/// Write a float without any tag.
+/**
+ * Write a float without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeFloatNoTag:(float)value;
-/// Write a uint64_t for the given field number.
+/**
+ * Write a uint64_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeUInt64:(int32_t)fieldNumber value:(uint64_t)value;
-/// Write a packed array of uint64_t for the given field number.
+/**
+ * Write a packed array of uint64_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ * @param tag The tag assigned to the values.
+ **/
- (void)writeUInt64Array:(int32_t)fieldNumber
values:(GPBUInt64Array *)values
tag:(uint32_t)tag;
-/// Write a uint64_t without any tag.
+/**
+ * Write a uint64_t without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeUInt64NoTag:(uint64_t)value;
-/// Write a int64_t for the given field number.
+/**
+ * Write a int64_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeInt64:(int32_t)fieldNumber value:(int64_t)value;
-/// Write a packed array of int64_t for the given field number.
+/**
+ * Write a packed array of int64_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ * @param tag The tag assigned to the values.
+ **/
- (void)writeInt64Array:(int32_t)fieldNumber
values:(GPBInt64Array *)values
tag:(uint32_t)tag;
-/// Write a int64_t without any tag.
+/**
+ * Write a int64_t without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeInt64NoTag:(int64_t)value;
-/// Write a int32_t for the given field number.
+/**
+ * Write a int32_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeInt32:(int32_t)fieldNumber value:(int32_t)value;
-/// Write a packed array of int32_t for the given field number.
+/**
+ * Write a packed array of int32_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ * @param tag The tag assigned to the values.
+ **/
- (void)writeInt32Array:(int32_t)fieldNumber
values:(GPBInt32Array *)values
tag:(uint32_t)tag;
-/// Write a int32_t without any tag.
+/**
+ * Write a int32_t without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeInt32NoTag:(int32_t)value;
-/// Write a uint32_t for the given field number.
+/**
+ * Write a uint32_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeUInt32:(int32_t)fieldNumber value:(uint32_t)value;
-/// Write a packed array of uint32_t for the given field number.
+/**
+ * Write a packed array of uint32_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ * @param tag The tag assigned to the values.
+ **/
- (void)writeUInt32Array:(int32_t)fieldNumber
values:(GPBUInt32Array *)values
tag:(uint32_t)tag;
-/// Write a uint32_t without any tag.
+/**
+ * Write a uint32_t without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeUInt32NoTag:(uint32_t)value;
-/// Write a uint64_t for the given field number.
+/**
+ * Write a uint64_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeFixed64:(int32_t)fieldNumber value:(uint64_t)value;
-/// Write a packed array of uint64_t for the given field number.
+/**
+ * Write a packed array of uint64_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ * @param tag The tag assigned to the values.
+ **/
- (void)writeFixed64Array:(int32_t)fieldNumber
values:(GPBUInt64Array *)values
tag:(uint32_t)tag;
-/// Write a uint64_t without any tag.
+/**
+ * Write a uint64_t without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeFixed64NoTag:(uint64_t)value;
-/// Write a uint32_t for the given field number.
+/**
+ * Write a uint32_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeFixed32:(int32_t)fieldNumber value:(uint32_t)value;
-/// Write a packed array of uint32_t for the given field number.
+/**
+ * Write a packed array of uint32_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ * @param tag The tag assigned to the values.
+ **/
- (void)writeFixed32Array:(int32_t)fieldNumber
values:(GPBUInt32Array *)values
tag:(uint32_t)tag;
-/// Write a uint32_t without any tag.
+/**
+ * Write a uint32_t without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeFixed32NoTag:(uint32_t)value;
-/// Write a int32_t for the given field number.
+/**
+ * Write a int32_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeSInt32:(int32_t)fieldNumber value:(int32_t)value;
-/// Write a packed array of int32_t for the given field number.
+/**
+ * Write a packed array of int32_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ * @param tag The tag assigned to the values.
+ **/
- (void)writeSInt32Array:(int32_t)fieldNumber
values:(GPBInt32Array *)values
tag:(uint32_t)tag;
-/// Write a int32_t without any tag.
+/**
+ * Write a int32_t without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeSInt32NoTag:(int32_t)value;
-/// Write a int64_t for the given field number.
+/**
+ * Write a int64_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeSInt64:(int32_t)fieldNumber value:(int64_t)value;
-/// Write a packed array of int64_t for the given field number.
+/**
+ * Write a packed array of int64_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ * @param tag The tag assigned to the values.
+ **/
- (void)writeSInt64Array:(int32_t)fieldNumber
values:(GPBInt64Array *)values
tag:(uint32_t)tag;
-/// Write a int64_t without any tag.
+/**
+ * Write a int64_t without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeSInt64NoTag:(int64_t)value;
-/// Write a int64_t for the given field number.
+/**
+ * Write a int64_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeSFixed64:(int32_t)fieldNumber value:(int64_t)value;
-/// Write a packed array of int64_t for the given field number.
+/**
+ * Write a packed array of int64_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ * @param tag The tag assigned to the values.
+ **/
- (void)writeSFixed64Array:(int32_t)fieldNumber
values:(GPBInt64Array *)values
tag:(uint32_t)tag;
-/// Write a int64_t without any tag.
+/**
+ * Write a int64_t without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeSFixed64NoTag:(int64_t)value;
-/// Write a int32_t for the given field number.
+/**
+ * Write a int32_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeSFixed32:(int32_t)fieldNumber value:(int32_t)value;
-/// Write a packed array of int32_t for the given field number.
+/**
+ * Write a packed array of int32_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ * @param tag The tag assigned to the values.
+ **/
- (void)writeSFixed32Array:(int32_t)fieldNumber
values:(GPBInt32Array *)values
tag:(uint32_t)tag;
-/// Write a int32_t without any tag.
+/**
+ * Write a int32_t without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeSFixed32NoTag:(int32_t)value;
-/// Write a BOOL for the given field number.
+/**
+ * Write a BOOL for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeBool:(int32_t)fieldNumber value:(BOOL)value;
-/// Write a packed array of BOOL for the given field number.
+/**
+ * Write a packed array of BOOL for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ * @param tag The tag assigned to the values.
+ **/
- (void)writeBoolArray:(int32_t)fieldNumber
values:(GPBBoolArray *)values
tag:(uint32_t)tag;
-/// Write a BOOL without any tag.
+/**
+ * Write a BOOL without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeBoolNoTag:(BOOL)value;
-/// Write a int32_t for the given field number.
+/**
+ * Write a int32_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeEnum:(int32_t)fieldNumber value:(int32_t)value;
-/// Write a packed array of int32_t for the given field number.
+/**
+ * Write a packed array of int32_t for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ * @param tag The tag assigned to the values.
+ **/
- (void)writeEnumArray:(int32_t)fieldNumber
values:(GPBEnumArray *)values
tag:(uint32_t)tag;
-/// Write a int32_t without any tag.
+/**
+ * Write a int32_t without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeEnumNoTag:(int32_t)value;
-/// Write a NSString for the given field number.
+/**
+ * Write a NSString for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeString:(int32_t)fieldNumber value:(NSString *)value;
-/// Write an array of NSString for the given field number.
+/**
+ * Write an array of NSString for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ **/
- (void)writeStringArray:(int32_t)fieldNumber values:(NSArray<NSString*> *)values;
-/// Write a NSString without any tag.
+/**
+ * Write a NSString without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeStringNoTag:(NSString *)value;
-/// Write a GPBMessage for the given field number.
+/**
+ * Write a GPBMessage for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeMessage:(int32_t)fieldNumber value:(GPBMessage *)value;
-/// Write an array of GPBMessage for the given field number.
+/**
+ * Write an array of GPBMessage for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ **/
- (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray<GPBMessage*> *)values;
-/// Write a GPBMessage without any tag.
+/**
+ * Write a GPBMessage without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeMessageNoTag:(GPBMessage *)value;
-/// Write a NSData for the given field number.
+/**
+ * Write a NSData for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeBytes:(int32_t)fieldNumber value:(NSData *)value;
-/// Write an array of NSData for the given field number.
+/**
+ * Write an array of NSData for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ **/
- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray<NSData*> *)values;
-/// Write a NSData without any tag.
+/**
+ * Write a NSData without any tag.
+ *
+ * @param value The value to write out.
+ **/
- (void)writeBytesNoTag:(NSData *)value;
-/// Write a GPBMessage for the given field number.
+/**
+ * Write a GPBMessage for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeGroup:(int32_t)fieldNumber
value:(GPBMessage *)value;
-/// Write an array of GPBMessage for the given field number.
+/**
+ * Write an array of GPBMessage for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ **/
- (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray<GPBMessage*> *)values;
-/// Write a GPBMessage without any tag (but does write the endGroup tag).
+/**
+ * Write a GPBMessage without any tag (but does write the endGroup tag).
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeGroupNoTag:(int32_t)fieldNumber
value:(GPBMessage *)value;
-/// Write a GPBUnknownFieldSet for the given field number.
+/**
+ * Write a GPBUnknownFieldSet for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeUnknownGroup:(int32_t)fieldNumber
value:(GPBUnknownFieldSet *)value;
-/// Write an array of GPBUnknownFieldSet for the given field number.
+/**
+ * Write an array of GPBUnknownFieldSet for the given field number.
+ *
+ * @param fieldNumber The field number assigned to the values.
+ * @param values The values to write out.
+ **/
- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray<GPBUnknownFieldSet*> *)values;
-/// Write a GPBUnknownFieldSet without any tag (but does write the endGroup tag).
+/**
+ * Write a GPBUnknownFieldSet without any tag (but does write the endGroup tag).
+ *
+ * @param fieldNumber The field number assigned to the value.
+ * @param value The value to write out.
+ **/
- (void)writeUnknownGroupNoTag:(int32_t)fieldNumber
value:(GPBUnknownFieldSet *)value;
//%PDDM-EXPAND-END _WRITE_DECLS()
-/// Write a MessageSet extension field to the stream. For historical reasons,
-/// the wire format differs from normal fields.
+/**
+Write a MessageSet extension field to the stream. For historical reasons,
+the wire format differs from normal fields.
+
+@param fieldNumber The extension field number to write out.
+@param value The message from where to get the extension.
+*/
- (void)writeMessageSetExtension:(int32_t)fieldNumber value:(GPBMessage *)value;
-/// Write an unparsed MessageSet extension field to the stream. For
-/// historical reasons, the wire format differs from normal fields.
+/**
+Write an unparsed MessageSet extension field to the stream. For historical
+reasons, the wire format differs from normal fields.
+
+@param fieldNumber The extension field number to write out.
+@param value The raw message from where to get the extension.
+*/
- (void)writeRawMessageSetExtension:(int32_t)fieldNumber value:(NSData *)value;
@end
@@ -291,32 +642,76 @@ NS_ASSUME_NONNULL_END
// Write methods for types that can be in packed arrays.
//%PDDM-DEFINE _WRITE_PACKABLE_DECLS(NAME, ARRAY_TYPE, TYPE)
-//%/// Write a TYPE for the given field number.
+//%/**
+//% * Write a TYPE for the given field number.
+//% *
+//% * @param fieldNumber The field number assigned to the value.
+//% * @param value The value to write out.
+//% **/
//%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE)value;
-//%/// Write a packed array of TYPE for the given field number.
+//%/**
+//% * Write a packed array of TYPE for the given field number.
+//% *
+//% * @param fieldNumber The field number assigned to the values.
+//% * @param values The values to write out.
+//% * @param tag The tag assigned to the values.
+//% **/
//%- (void)write##NAME##Array:(int32_t)fieldNumber
//% NAME$S values:(GPB##ARRAY_TYPE##Array *)values
//% NAME$S tag:(uint32_t)tag;
-//%/// Write a TYPE without any tag.
+//%/**
+//% * Write a TYPE without any tag.
+//% *
+//% * @param value The value to write out.
+//% **/
//%- (void)write##NAME##NoTag:(TYPE)value;
//%
// Write methods for types that aren't in packed arrays.
//%PDDM-DEFINE _WRITE_UNPACKABLE_DECLS(NAME, TYPE)
-//%/// Write a TYPE for the given field number.
+//%/**
+//% * Write a TYPE for the given field number.
+//% *
+//% * @param fieldNumber The field number assigned to the value.
+//% * @param value The value to write out.
+//% **/
//%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE *)value;
-//%/// Write an array of TYPE for the given field number.
+//%/**
+//% * Write an array of TYPE for the given field number.
+//% *
+//% * @param fieldNumber The field number assigned to the values.
+//% * @param values The values to write out.
+//% **/
//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray<##TYPE##*> *)values;
-//%/// Write a TYPE without any tag.
+//%/**
+//% * Write a TYPE without any tag.
+//% *
+//% * @param value The value to write out.
+//% **/
//%- (void)write##NAME##NoTag:(TYPE *)value;
//%
// Special write methods for Groups.
//%PDDM-DEFINE _WRITE_GROUP_DECLS(NAME, TYPE)
-//%/// Write a TYPE for the given field number.
+//%/**
+//% * Write a TYPE for the given field number.
+//% *
+//% * @param fieldNumber The field number assigned to the value.
+//% * @param value The value to write out.
+//% **/
//%- (void)write##NAME:(int32_t)fieldNumber
//% NAME$S value:(TYPE *)value;
-//%/// Write an array of TYPE for the given field number.
+//%/**
+//% * Write an array of TYPE for the given field number.
+//% *
+//% * @param fieldNumber The field number assigned to the values.
+//% * @param values The values to write out.
+//% **/
//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray<##TYPE##*> *)values;
-//%/// Write a TYPE without any tag (but does write the endGroup tag).
+//%/**
+//% * Write a TYPE without any tag (but does write the endGroup tag).
+//% *
+//% * @param fieldNumber The field number assigned to the value.
+//% * @param value The value to write out.
+//% **/
//%- (void)write##NAME##NoTag:(int32_t)fieldNumber
//% NAME$S value:(TYPE *)value;
//%
diff --git a/objectivec/GPBCodedOutputStream.m b/objectivec/GPBCodedOutputStream.m
index 63ba8068..7c3ab447 100644
--- a/objectivec/GPBCodedOutputStream.m
+++ b/objectivec/GPBCodedOutputStream.m
@@ -144,22 +144,6 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state,
GPBWriteRawByte(state, (int32_t)(value >> 56) & 0xFF);
}
-#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS)
-+ (void)load {
- // This test exists to verify that CFStrings with embedded NULLs will work
- // for us. If this Assert fails, all code below that depends on
- // CFStringGetCStringPtr will NOT work properly on strings that contain
- // embedded NULLs, and we do get that in some protobufs.
- // Note that this will not be compiled in release.
- // We didn't feel that just keeping it in a unit test was sufficient because
- // the Protobuf unit tests are only run when somebody is actually working
- // on protobufs.
- CFStringRef zeroTest = CFSTR("Test\0String");
- const char *cString = CFStringGetCStringPtr(zeroTest, kCFStringEncodingUTF8);
- NSAssert(cString == NULL, @"Serious Error");
-}
-#endif // DEBUG && !defined(NS_BLOCK_ASSERTIONS)
-
- (void)dealloc {
[self flush];
[state_.output close];
@@ -282,19 +266,15 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state,
}
- (void)writeStringNoTag:(const NSString *)value {
- // If you are concerned about embedded NULLs see the test in
- // +load above.
- const char *quickString =
- CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingUTF8);
- size_t length = (quickString != NULL)
- ? strlen(quickString)
- : [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
+ size_t length = [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
GPBWriteRawVarint32(&state_, (int32_t)length);
-
if (length == 0) {
return;
}
+ const char *quickString =
+ CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingUTF8);
+
// Fast path: Most strings are short, if the buffer already has space,
// add to it directly.
NSUInteger bufferBytesLeft = state_.size - state_.position;
@@ -310,7 +290,7 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state,
maxLength:bufferBytesLeft
usedLength:&usedBufferLength
encoding:NSUTF8StringEncoding
- options:0
+ options:(NSStringEncodingConversionOptions)0
range:NSMakeRange(0, [value length])
remainingRange:NULL];
}
@@ -1038,14 +1018,7 @@ size_t GPBComputeBoolSizeNoTag(BOOL value) {
}
size_t GPBComputeStringSizeNoTag(NSString *value) {
- // If you are concerned about embedded NULLs see the test in
- // +load above.
- const char *quickString =
- CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingUTF8);
- NSUInteger length =
- (quickString != NULL)
- ? strlen(quickString)
- : [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
+ NSUInteger length = [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
return GPBComputeRawVarint32SizeForInteger(length) + length;
}
diff --git a/objectivec/GPBDescriptor.h b/objectivec/GPBDescriptor.h
index fe4ff390..651f4de0 100644
--- a/objectivec/GPBDescriptor.h
+++ b/objectivec/GPBDescriptor.h
@@ -39,104 +39,250 @@
NS_ASSUME_NONNULL_BEGIN
+/** Syntax used in the proto file. */
typedef NS_ENUM(uint8_t, GPBFileSyntax) {
+ /** Unknown syntax. */
GPBFileSyntaxUnknown = 0,
+ /** Proto2 syntax. */
GPBFileSyntaxProto2 = 2,
+ /** Proto3 syntax. */
GPBFileSyntaxProto3 = 3,
};
+/** Type of proto field. */
typedef NS_ENUM(uint8_t, GPBFieldType) {
- GPBFieldTypeSingle, // optional/required
- GPBFieldTypeRepeated, // repeated
- GPBFieldTypeMap, // map<K,V>
+ /** Optional/required field. Only valid for proto2 fields. */
+ GPBFieldTypeSingle,
+ /** Repeated field. */
+ GPBFieldTypeRepeated,
+ /** Map field. */
+ GPBFieldTypeMap,
};
+/**
+ * Describes a proto message.
+ **/
@interface GPBDescriptor : NSObject<NSCopying>
+/** Name of the message. */
@property(nonatomic, readonly, copy) NSString *name;
+/** Fields declared in the message. */
@property(nonatomic, readonly, strong, nullable) NSArray<GPBFieldDescriptor*> *fields;
+/** Oneofs declared in the message. */
@property(nonatomic, readonly, strong, nullable) NSArray<GPBOneofDescriptor*> *oneofs;
+/** Extension range declared for the message. */
@property(nonatomic, readonly, nullable) const GPBExtensionRange *extensionRanges;
+/** Number of extension ranges declared for the message. */
@property(nonatomic, readonly) uint32_t extensionRangesCount;
+/** Descriptor for the file where the message was defined. */
@property(nonatomic, readonly, assign) GPBFileDescriptor *file;
+/** Whether the message is in wire format or not. */
@property(nonatomic, readonly, getter=isWireFormat) BOOL wireFormat;
+/** The class of this message. */
@property(nonatomic, readonly) Class messageClass;
+/** Containing message descriptor if this message is nested, or nil otherwise. */
+@property(readonly, nullable) GPBDescriptor *containingType;
+/**
+ * Fully qualified name for this message (package.message). Can be nil if the
+ * value is unable to be computed.
+ */
+@property(readonly, nullable) NSString *fullName;
+/**
+ * Gets the field for the given number.
+ *
+ * @param fieldNumber The number for the field to get.
+ *
+ * @return The field descriptor for the given number, or nil if not found.
+ **/
- (nullable GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber;
+
+/**
+ * Gets the field for the given name.
+ *
+ * @param name The name for the field to get.
+ *
+ * @return The field descriptor for the given name, or nil if not found.
+ **/
- (nullable GPBFieldDescriptor *)fieldWithName:(NSString *)name;
+
+/**
+ * Gets the oneof for the given name.
+ *
+ * @param name The name for the oneof to get.
+ *
+ * @return The oneof descriptor for the given name, or nil if not found.
+ **/
- (nullable GPBOneofDescriptor *)oneofWithName:(NSString *)name;
@end
+/**
+ * Describes a proto file.
+ **/
@interface GPBFileDescriptor : NSObject
+/** The package declared in the proto file. */
@property(nonatomic, readonly, copy) NSString *package;
+/** The objc prefix declared in the proto file. */
+@property(nonatomic, readonly, copy, nullable) NSString *objcPrefix;
+/** The syntax of the proto file. */
@property(nonatomic, readonly) GPBFileSyntax syntax;
@end
+/**
+ * Describes a oneof field.
+ **/
@interface GPBOneofDescriptor : NSObject
+/** Name of the oneof field. */
@property(nonatomic, readonly) NSString *name;
+/** Fields declared in the oneof. */
@property(nonatomic, readonly) NSArray<GPBFieldDescriptor*> *fields;
+/**
+ * Gets the field for the given number.
+ *
+ * @param fieldNumber The number for the field to get.
+ *
+ * @return The field descriptor for the given number, or nil if not found.
+ **/
- (nullable GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber;
+
+/**
+ * Gets the field for the given name.
+ *
+ * @param name The name for the field to get.
+ *
+ * @return The field descriptor for the given name, or nil if not found.
+ **/
- (nullable GPBFieldDescriptor *)fieldWithName:(NSString *)name;
+
@end
+/**
+ * Describes a proto field.
+ **/
@interface GPBFieldDescriptor : NSObject
+/** Name of the field. */
@property(nonatomic, readonly, copy) NSString *name;
+/** Number associated with the field. */
@property(nonatomic, readonly) uint32_t number;
+/** Data type contained in the field. */
@property(nonatomic, readonly) GPBDataType dataType;
+/** Whether it has a default value or not. */
@property(nonatomic, readonly) BOOL hasDefaultValue;
+/** Default value for the field. */
@property(nonatomic, readonly) GPBGenericValue defaultValue;
+/** Whether this field is required. Only valid for proto2 fields. */
@property(nonatomic, readonly, getter=isRequired) BOOL required;
+/** Whether this field is optional. */
@property(nonatomic, readonly, getter=isOptional) BOOL optional;
+/** Type of field (single, repeated, map). */
@property(nonatomic, readonly) GPBFieldType fieldType;
-// If it is a map, the value type is in -type.
+/** Type of the key if the field is a map. The value's type is -fieldType. */
@property(nonatomic, readonly) GPBDataType mapKeyDataType;
+/** Whether the field is packable. */
@property(nonatomic, readonly, getter=isPackable) BOOL packable;
+/** The containing oneof if this field is part of one, nil otherwise. */
@property(nonatomic, readonly, assign, nullable) GPBOneofDescriptor *containingOneof;
-// Message properties
+/** Class of the message if the field is of message type. */
@property(nonatomic, readonly, assign, nullable) Class msgClass;
-// Enum properties
+/** Descriptor for the enum if this field is an enum. */
@property(nonatomic, readonly, strong, nullable) GPBEnumDescriptor *enumDescriptor;
+/**
+ * Checks whether the given enum raw value is a valid enum value.
+ *
+ * @param value The raw enum value to check.
+ *
+ * @return YES if value is a valid enum raw value.
+ **/
- (BOOL)isValidEnumValue:(int32_t)value;
-// For now, this will return nil if it doesn't know the name to use for
-// TextFormat.
+/** @return Name for the text format, or nil if not known. */
- (nullable NSString *)textFormatName;
@end
+/**
+ * Describes a proto enum.
+ **/
@interface GPBEnumDescriptor : NSObject
+/** Name of the enum. */
@property(nonatomic, readonly, copy) NSString *name;
+/** Function that validates that raw values are valid enum values. */
@property(nonatomic, readonly) GPBEnumValidationFunc enumVerifier;
+/**
+ * Returns the enum value name for the given raw enum.
+ *
+ * @param number The raw enum value.
+ *
+ * @return The name of the enum value passed, or nil if not valid.
+ **/
- (nullable NSString *)enumNameForValue:(int32_t)number;
+
+/**
+ * Gets the enum raw value for the given enum name.
+ *
+ * @param outValue A pointer where the value will be set.
+ * @param name The enum name for which to get the raw value.
+ *
+ * @return YES if a value was copied into the pointer, NO otherwise.
+ **/
- (BOOL)getValue:(nullable int32_t *)outValue forEnumName:(NSString *)name;
+/**
+ * Returns the text format for the given raw enum value.
+ *
+ * @param number The raw enum value.
+ *
+ * @return The text format name for the raw enum value, or nil if not valid.
+ **/
- (nullable NSString *)textFormatNameForValue:(int32_t)number;
+
+/**
+ * Gets the enum raw value for the given text format name.
+ *
+ * @param outValue A pointer where the value will be set.
+ * @param textFormatName The text format name for which to get the raw value.
+ *
+ * @return YES if a value was copied into the pointer, NO otherwise.
+ **/
- (BOOL)getValue:(nullable int32_t *)outValue forEnumTextFormatName:(NSString *)textFormatName;
@end
+/**
+ * Describes a proto extension.
+ **/
@interface GPBExtensionDescriptor : NSObject<NSCopying>
+/** Field number under which the extension is stored. */
@property(nonatomic, readonly) uint32_t fieldNumber;
+/** The containing message class, i.e. the class extended by this extension. */
@property(nonatomic, readonly) Class containingMessageClass;
+/** Data type contained in the extension. */
@property(nonatomic, readonly) GPBDataType dataType;
+/** Whether the extension is repeated. */
@property(nonatomic, readonly, getter=isRepeated) BOOL repeated;
+/** Whether the extension is packable. */
@property(nonatomic, readonly, getter=isPackable) BOOL packable;
+/** The class of the message if the extension is of message type. */
@property(nonatomic, readonly, assign) Class msgClass;
+/** The singleton name for the extension. */
@property(nonatomic, readonly) NSString *singletonName;
+/** The enum descriptor if the extension is of enum type. */
@property(nonatomic, readonly, strong, nullable) GPBEnumDescriptor *enumDescriptor;
+/** The default value for the extension. */
@property(nonatomic, readonly, nullable) id defaultValue;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m
index dccb9bc8..0753a948 100644
--- a/objectivec/GPBDescriptor.m
+++ b/objectivec/GPBDescriptor.m
@@ -42,8 +42,10 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdirect-ivar-access"
-// The address of this variable is used as a key for obj_getAssociatedObject.
+// The addresses of these variables are used as keys for objc_getAssociatedObject.
static const char kTextFormatExtraValueKey = 0;
+static const char kParentClassNameValueKey = 0;
+static const char kClassNameSuffixKey = 0;
// Utility function to generate selectors on the fly.
static SEL SelFromStrings(const char *prefix, const char *middle,
@@ -215,10 +217,102 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
extensionRangesCount_ = count;
}
+- (void)setupContainingMessageClassName:(const char *)msgClassName {
+ // Note: Only fetch the class here, can't send messages to it because
+ // that could cause cycles back to this class within +initialize if
+ // two messages have each other in fields (i.e. - they build a graph).
+ NSAssert(objc_getClass(msgClassName), @"Class %s not defined", msgClassName);
+ NSValue *parentNameValue = [NSValue valueWithPointer:msgClassName];
+ objc_setAssociatedObject(self, &kParentClassNameValueKey,
+ parentNameValue,
+ OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (void)setupMessageClassNameSuffix:(NSString *)suffix {
+ if (suffix.length) {
+ objc_setAssociatedObject(self, &kClassNameSuffixKey,
+ suffix,
+ OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+ }
+}
+
- (NSString *)name {
return NSStringFromClass(messageClass_);
}
+- (GPBDescriptor *)containingType {
+ NSValue *parentNameValue =
+ objc_getAssociatedObject(self, &kParentClassNameValueKey);
+ if (!parentNameValue) {
+ return nil;
+ }
+ const char *parentName = [parentNameValue pointerValue];
+ Class parentClass = objc_getClass(parentName);
+ NSAssert(parentClass, @"Class %s not defined", parentName);
+ return [parentClass descriptor];
+}
+
+- (NSString *)fullName {
+ NSString *className = NSStringFromClass(self.messageClass);
+ GPBFileDescriptor *file = self.file;
+ NSString *objcPrefix = file.objcPrefix;
+ if (objcPrefix && ![className hasPrefix:objcPrefix]) {
+ NSAssert(0,
+ @"Class didn't have correct prefix? (%@ - %@)",
+ className, objcPrefix);
+ return nil;
+ }
+ GPBDescriptor *parent = self.containingType;
+
+ NSString *name = nil;
+ if (parent) {
+ NSString *parentClassName = NSStringFromClass(parent.messageClass);
+ // The generator will add _Class to avoid reserved words, drop it.
+ NSString *suffix = objc_getAssociatedObject(parent, &kClassNameSuffixKey);
+ if (suffix) {
+ if (![parentClassName hasSuffix:suffix]) {
+ NSAssert(0,
+ @"ParentMessage class didn't have correct suffix? (%@ - %@)",
+ className, suffix);
+ return nil;
+ }
+ parentClassName =
+ [parentClassName substringToIndex:(parentClassName.length - suffix.length)];
+ }
+ NSString *parentPrefix = [parentClassName stringByAppendingString:@"_"];
+ if (![className hasPrefix:parentPrefix]) {
+ NSAssert(0,
+ @"Class didn't have the correct parent name prefix? (%@ - %@)",
+ parentPrefix, className);
+ return nil;
+ }
+ name = [className substringFromIndex:parentPrefix.length];
+ } else {
+ name = [className substringFromIndex:objcPrefix.length];
+ }
+
+ // The generator will add _Class to avoid reserved words, drop it.
+ NSString *suffix = objc_getAssociatedObject(self, &kClassNameSuffixKey);
+ if (suffix) {
+ if (![name hasSuffix:suffix]) {
+ NSAssert(0,
+ @"Message class didn't have correct suffix? (%@ - %@)",
+ name, suffix);
+ return nil;
+ }
+ name = [name substringToIndex:(name.length - suffix.length)];
+ }
+
+ NSString *prefix = (parent != nil ? parent.fullName : file.package);
+ NSString *result;
+ if (prefix.length > 0) {
+ result = [NSString stringWithFormat:@"%@.%@", prefix, name];
+ } else {
+ result = name;
+ }
+ return result;
+}
+
- (id)copyWithZone:(NSZone *)zone {
#pragma unused(zone)
return [self retain];
@@ -255,13 +349,27 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
@implementation GPBFileDescriptor {
NSString *package_;
+ NSString *objcPrefix_;
GPBFileSyntax syntax_;
}
@synthesize package = package_;
+@synthesize objcPrefix = objcPrefix_;
@synthesize syntax = syntax_;
- (instancetype)initWithPackage:(NSString *)package
+ objcPrefix:(NSString *)objcPrefix
+ syntax:(GPBFileSyntax)syntax {
+ self = [super init];
+ if (self) {
+ package_ = [package copy];
+ objcPrefix_ = [objcPrefix copy];
+ syntax_ = syntax;
+ }
+ return self;
+}
+
+- (instancetype)initWithPackage:(NSString *)package
syntax:(GPBFileSyntax)syntax {
self = [super init];
if (self) {
@@ -273,6 +381,7 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
- (void)dealloc {
[package_ release];
+ [objcPrefix_ release];
[super dealloc];
}
@@ -416,6 +525,9 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
// Extra type specific data.
if (isMessage) {
const char *className = coreDesc->dataTypeSpecific.className;
+ // Note: Only fetch the class here, can't send messages to it because
+ // that could cause cycles back to this class within +initialize if
+ // two messages have each other in fields (i.e. - they build a graph).
msgClass_ = objc_getClass(className);
NSAssert(msgClass_, @"Class %s not defined", className);
} else if (dataType == GPBDataTypeEnum) {
diff --git a/objectivec/GPBDescriptor_PackagePrivate.h b/objectivec/GPBDescriptor_PackagePrivate.h
index c20ff6b0..9173e7a2 100644
--- a/objectivec/GPBDescriptor_PackagePrivate.h
+++ b/objectivec/GPBDescriptor_PackagePrivate.h
@@ -37,6 +37,7 @@
// Describes attributes of the field.
typedef NS_OPTIONS(uint16_t, GPBFieldFlags) {
+ GPBFieldNone = 0,
// These map to standard protobuf concepts.
GPBFieldRequired = 1 << 0,
GPBFieldRepeated = 1 << 1,
@@ -111,6 +112,7 @@ typedef struct GPBMessageFieldDescriptionWithDefault {
// Describes attributes of the extension.
typedef NS_OPTIONS(uint8_t, GPBExtensionOptions) {
+ GPBExtensionNone = 0,
// These map to standard protobuf concepts.
GPBExtensionRepeated = 1 << 0,
GPBExtensionPacked = 1 << 1,
@@ -130,6 +132,7 @@ typedef struct GPBExtensionDescription {
} GPBExtensionDescription;
typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) {
+ GPBDescriptorInitializationFlag_None = 0,
GPBDescriptorInitializationFlag_FieldsWithDefault = 1 << 0,
GPBDescriptorInitializationFlag_WireFormat = 1 << 1,
};
@@ -165,11 +168,16 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) {
firstHasIndex:(int32_t)firstHasIndex;
- (void)setupExtraTextInfo:(const char *)extraTextFormatInfo;
- (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count;
+- (void)setupContainingMessageClassName:(const char *)msgClassName;
+- (void)setupMessageClassNameSuffix:(NSString *)suffix;
@end
@interface GPBFileDescriptor ()
- (instancetype)initWithPackage:(NSString *)package
+ objcPrefix:(NSString *)objcPrefix
+ syntax:(GPBFileSyntax)syntax;
+- (instancetype)initWithPackage:(NSString *)package
syntax:(GPBFileSyntax)syntax;
@end
diff --git a/objectivec/GPBDictionary.h b/objectivec/GPBDictionary.h
index f7959960..4b2b9ff3 100644
--- a/objectivec/GPBDictionary.h
+++ b/objectivec/GPBDictionary.h
@@ -32,11 +32,6 @@
#import "GPBRuntimeTypes.h"
-// These classes are used for map fields of basic data types. They are used because
-// they perform better than boxing into NSNumbers in NSDictionaries.
-
-// Note: These are not meant to be subclassed.
-
// Note on naming: for the classes holding numeric values, a more natural
// naming of the method might be things like "-valueForKey:",
// "-setValue:forKey:"; etc. But those selectors are also defined by Key Value
@@ -53,289 +48,1134 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - UInt32 -> UInt32
+/**
+ * Class used for map fields of <uint32_t, uint32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt32UInt32Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithUInt32:(uint32_t)value
forKey:(uint32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithUInt32s:(const uint32_t [])values
forKeys:(const uint32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithUInt32s:(const uint32_t [])values
forKeys:(const uint32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(uint32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndUInt32sUsingBlock:
(void (^)(uint32_t key, uint32_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBUInt32UInt32Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setUInt32:(uint32_t)value forKey:(uint32_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeUInt32ForKey:(uint32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt32 -> Int32
+/**
+ * Class used for map fields of <uint32_t, int32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt32Int32Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithInt32:(int32_t)value
forKey:(uint32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithInt32s:(const int32_t [])values
forKeys:(const uint32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt32Int32Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithInt32s:(const int32_t [])values
forKeys:(const uint32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBUInt32Int32Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getInt32:(nullable int32_t *)value forKey:(uint32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndInt32sUsingBlock:
(void (^)(uint32_t key, int32_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBUInt32Int32Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setInt32:(int32_t)value forKey:(uint32_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeInt32ForKey:(uint32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt32 -> UInt64
+/**
+ * Class used for map fields of <uint32_t, uint64_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt32UInt64Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithUInt64:(uint64_t)value
forKey:(uint32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithUInt64s:(const uint64_t [])values
forKeys:(const uint32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithUInt64s:(const uint64_t [])values
forKeys:(const uint32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(uint32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndUInt64sUsingBlock:
(void (^)(uint32_t key, uint64_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBUInt32UInt64Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setUInt64:(uint64_t)value forKey:(uint32_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeUInt64ForKey:(uint32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt32 -> Int64
+/**
+ * Class used for map fields of <uint32_t, int64_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt32Int64Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithInt64:(int64_t)value
forKey:(uint32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithInt64s:(const int64_t [])values
forKeys:(const uint32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt32Int64Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithInt64s:(const int64_t [])values
forKeys:(const uint32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBUInt32Int64Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getInt64:(nullable int64_t *)value forKey:(uint32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndInt64sUsingBlock:
(void (^)(uint32_t key, int64_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBUInt32Int64Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setInt64:(int64_t)value forKey:(uint32_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeInt64ForKey:(uint32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt32 -> Bool
+/**
+ * Class used for map fields of <uint32_t, BOOL>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt32BoolDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithBool:(BOOL)value
forKey:(uint32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithBools:(const BOOL [])values
forKeys:(const uint32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt32BoolDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithBools:(const BOOL [])values
forKeys:(const uint32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBUInt32BoolDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getBool:(nullable BOOL *)value forKey:(uint32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndBoolsUsingBlock:
(void (^)(uint32_t key, BOOL value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBUInt32BoolDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setBool:(BOOL)value forKey:(uint32_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeBoolForKey:(uint32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt32 -> Float
+/**
+ * Class used for map fields of <uint32_t, float>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt32FloatDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithFloat:(float)value
forKey:(uint32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithFloats:(const float [])values
forKeys:(const uint32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt32FloatDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithFloats:(const float [])values
forKeys:(const uint32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBUInt32FloatDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getFloat:(nullable float *)value forKey:(uint32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndFloatsUsingBlock:
(void (^)(uint32_t key, float value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBUInt32FloatDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setFloat:(float)value forKey:(uint32_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeFloatForKey:(uint32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt32 -> Double
+/**
+ * Class used for map fields of <uint32_t, double>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt32DoubleDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithDouble:(double)value
forKey:(uint32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithDoubles:(const double [])values
forKeys:(const uint32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt32DoubleDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithDoubles:(const double [])values
forKeys:(const uint32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBUInt32DoubleDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getDouble:(nullable double *)value forKey:(uint32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndDoublesUsingBlock:
(void (^)(uint32_t key, double value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBUInt32DoubleDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setDouble:(double)value forKey:(uint32_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeDoubleForKey:(uint32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt32 -> Enum
+/**
+ * Class used for map fields of <uint32_t, int32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt32EnumDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/** The validation function to check if the enums are valid. */
@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given validation function.
+ *
+ * @param func The enum validation function for the dictionary.
+ *
+ * @return A newly instanced dictionary.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param rawValue The raw enum value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValue:(int32_t)rawValue
forKey:(uint32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param values The raw enum values values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValues:(const int32_t [])values
forKeys:(const uint32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt32EnumDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
capacity:(NSUInteger)numItems;
+/**
+ * Initializes a dictionary with the given validation function.
+ *
+ * @param func The enum validation function for the dictionary.
+ *
+ * @return A newly initialized dictionary.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+
+/**
+ * Initializes a dictionary with the entries given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param values The raw enum values values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly initialized dictionary with the keys and values in it.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValues:(const int32_t [])values
forKeys:(const uint32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly initialized dictionary with the entries from the given
+ * dictionary in it.
+ **/
- (instancetype)initWithDictionary:(GPBUInt32EnumDictionary *)dictionary;
+
+/**
+ * Initializes a dictionary with the given capacity.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly initialized dictionary with the given capacity.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
capacity:(NSUInteger)numItems;
@@ -343,23 +1183,63 @@ NS_ASSUME_NONNULL_BEGIN
// is not a valid enumerator as defined by validationFunc. If the actual value is
// desired, use "raw" version of the method.
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getEnum:(nullable int32_t *)value forKey:(uint32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndEnumsUsingBlock:
(void (^)(uint32_t key, int32_t value, BOOL *stop))block;
-// These methods bypass the validationFunc to provide access to values that were not
-// known at the time the binary was compiled.
-
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the raw enum value for the given key.
+ *
+ * @note This method bypass the validationFunc to enable the access of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param rawValue Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(uint32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @note This method bypass the validationFunc to enable the access of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **rawValue**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndRawValuesUsingBlock:
(void (^)(uint32_t key, int32_t rawValue, BOOL *stop))block;
+/**
+ * Adds the keys and raw enum values from another dictionary.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addRawEntriesFromDictionary:(GPBUInt32EnumDictionary *)otherDictionary;
// If value is not a valid enumerator as defined by validationFunc, these
@@ -367,339 +1247,1312 @@ NS_ASSUME_NONNULL_BEGIN
// to the default value. Use the rawValue methods below to assign non enumerator
// values.
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setEnum:(int32_t)value forKey:(uint32_t)key;
-// This method bypass the validationFunc to provide setting of values that were not
-// known at the time the binary was compiled.
+/**
+ * Sets the raw enum value for the given key.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param rawValue The raw enum value to set.
+ * @param key The key under which to store the raw enum value.
+ **/
- (void)setRawValue:(int32_t)rawValue forKey:(uint32_t)key;
-// No validation applies to these methods.
-
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeEnumForKey:(uint32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt32 -> Object
+/**
+ * Class used for map fields of <uint32_t, ObjectType>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt32ObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param object The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithObject:(ObjectType)object
forKey:(uint32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param objects The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
forKeys:(const uint32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt32ObjectDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param objects The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
forKeys:(const uint32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBUInt32ObjectDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
+/**
+ * Fetches the object stored under the given key.
+ *
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return The object if found, nil otherwise.
+ **/
- (ObjectType)objectForKey:(uint32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **object**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndObjectsUsingBlock:
(void (^)(uint32_t key, ObjectType object, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBUInt32ObjectDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param object The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setObject:(ObjectType)object forKey:(uint32_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeObjectForKey:(uint32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int32 -> UInt32
+/**
+ * Class used for map fields of <int32_t, uint32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt32UInt32Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithUInt32:(uint32_t)value
forKey:(int32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithUInt32s:(const uint32_t [])values
forKeys:(const int32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt32UInt32Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithUInt32s:(const uint32_t [])values
forKeys:(const int32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBInt32UInt32Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(int32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndUInt32sUsingBlock:
(void (^)(int32_t key, uint32_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBInt32UInt32Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setUInt32:(uint32_t)value forKey:(int32_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeUInt32ForKey:(int32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int32 -> Int32
+/**
+ * Class used for map fields of <int32_t, int32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt32Int32Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithInt32:(int32_t)value
forKey:(int32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithInt32s:(const int32_t [])values
forKeys:(const int32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt32Int32Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithInt32s:(const int32_t [])values
forKeys:(const int32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBInt32Int32Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getInt32:(nullable int32_t *)value forKey:(int32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndInt32sUsingBlock:
(void (^)(int32_t key, int32_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBInt32Int32Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setInt32:(int32_t)value forKey:(int32_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeInt32ForKey:(int32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int32 -> UInt64
+/**
+ * Class used for map fields of <int32_t, uint64_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt32UInt64Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithUInt64:(uint64_t)value
forKey:(int32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithUInt64s:(const uint64_t [])values
forKeys:(const int32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt32UInt64Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithUInt64s:(const uint64_t [])values
forKeys:(const int32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBInt32UInt64Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(int32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndUInt64sUsingBlock:
(void (^)(int32_t key, uint64_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBInt32UInt64Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setUInt64:(uint64_t)value forKey:(int32_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeUInt64ForKey:(int32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int32 -> Int64
+/**
+ * Class used for map fields of <int32_t, int64_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt32Int64Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithInt64:(int64_t)value
forKey:(int32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithInt64s:(const int64_t [])values
forKeys:(const int32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt32Int64Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithInt64s:(const int64_t [])values
forKeys:(const int32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBInt32Int64Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getInt64:(nullable int64_t *)value forKey:(int32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndInt64sUsingBlock:
(void (^)(int32_t key, int64_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBInt32Int64Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setInt64:(int64_t)value forKey:(int32_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeInt64ForKey:(int32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int32 -> Bool
+/**
+ * Class used for map fields of <int32_t, BOOL>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt32BoolDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithBool:(BOOL)value
forKey:(int32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithBools:(const BOOL [])values
forKeys:(const int32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt32BoolDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithBools:(const BOOL [])values
forKeys:(const int32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBInt32BoolDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getBool:(nullable BOOL *)value forKey:(int32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndBoolsUsingBlock:
(void (^)(int32_t key, BOOL value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBInt32BoolDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setBool:(BOOL)value forKey:(int32_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeBoolForKey:(int32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int32 -> Float
+/**
+ * Class used for map fields of <int32_t, float>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt32FloatDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithFloat:(float)value
forKey:(int32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithFloats:(const float [])values
forKeys:(const int32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt32FloatDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithFloats:(const float [])values
forKeys:(const int32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBInt32FloatDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getFloat:(nullable float *)value forKey:(int32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndFloatsUsingBlock:
(void (^)(int32_t key, float value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBInt32FloatDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setFloat:(float)value forKey:(int32_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeFloatForKey:(int32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int32 -> Double
+/**
+ * Class used for map fields of <int32_t, double>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt32DoubleDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithDouble:(double)value
forKey:(int32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithDoubles:(const double [])values
forKeys:(const int32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt32DoubleDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithDoubles:(const double [])values
forKeys:(const int32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBInt32DoubleDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getDouble:(nullable double *)value forKey:(int32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndDoublesUsingBlock:
(void (^)(int32_t key, double value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBInt32DoubleDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setDouble:(double)value forKey:(int32_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeDoubleForKey:(int32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int32 -> Enum
+/**
+ * Class used for map fields of <int32_t, int32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt32EnumDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/** The validation function to check if the enums are valid. */
@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given validation function.
+ *
+ * @param func The enum validation function for the dictionary.
+ *
+ * @return A newly instanced dictionary.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param rawValue The raw enum value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValue:(int32_t)rawValue
forKey:(int32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param values The raw enum values values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValues:(const int32_t [])values
forKeys:(const int32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt32EnumDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
capacity:(NSUInteger)numItems;
+/**
+ * Initializes a dictionary with the given validation function.
+ *
+ * @param func The enum validation function for the dictionary.
+ *
+ * @return A newly initialized dictionary.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+
+/**
+ * Initializes a dictionary with the entries given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param values The raw enum values values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly initialized dictionary with the keys and values in it.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValues:(const int32_t [])values
forKeys:(const int32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly initialized dictionary with the entries from the given
+ * dictionary in it.
+ **/
- (instancetype)initWithDictionary:(GPBInt32EnumDictionary *)dictionary;
+
+/**
+ * Initializes a dictionary with the given capacity.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly initialized dictionary with the given capacity.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
capacity:(NSUInteger)numItems;
@@ -707,23 +2560,63 @@ NS_ASSUME_NONNULL_BEGIN
// is not a valid enumerator as defined by validationFunc. If the actual value is
// desired, use "raw" version of the method.
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getEnum:(nullable int32_t *)value forKey:(int32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndEnumsUsingBlock:
(void (^)(int32_t key, int32_t value, BOOL *stop))block;
-// These methods bypass the validationFunc to provide access to values that were not
-// known at the time the binary was compiled.
-
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the raw enum value for the given key.
+ *
+ * @note This method bypass the validationFunc to enable the access of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param rawValue Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(int32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @note This method bypass the validationFunc to enable the access of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **rawValue**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndRawValuesUsingBlock:
(void (^)(int32_t key, int32_t rawValue, BOOL *stop))block;
+/**
+ * Adds the keys and raw enum values from another dictionary.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addRawEntriesFromDictionary:(GPBInt32EnumDictionary *)otherDictionary;
// If value is not a valid enumerator as defined by validationFunc, these
@@ -731,339 +2624,1312 @@ NS_ASSUME_NONNULL_BEGIN
// to the default value. Use the rawValue methods below to assign non enumerator
// values.
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setEnum:(int32_t)value forKey:(int32_t)key;
-// This method bypass the validationFunc to provide setting of values that were not
-// known at the time the binary was compiled.
+/**
+ * Sets the raw enum value for the given key.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param rawValue The raw enum value to set.
+ * @param key The key under which to store the raw enum value.
+ **/
- (void)setRawValue:(int32_t)rawValue forKey:(int32_t)key;
-// No validation applies to these methods.
-
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeEnumForKey:(int32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int32 -> Object
+/**
+ * Class used for map fields of <int32_t, ObjectType>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt32ObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param object The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithObject:(ObjectType)object
forKey:(int32_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param objects The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
forKeys:(const int32_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt32ObjectDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param objects The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
forKeys:(const int32_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBInt32ObjectDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
+/**
+ * Fetches the object stored under the given key.
+ *
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return The object if found, nil otherwise.
+ **/
- (ObjectType)objectForKey:(int32_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **object**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndObjectsUsingBlock:
(void (^)(int32_t key, ObjectType object, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBInt32ObjectDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param object The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setObject:(ObjectType)object forKey:(int32_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeObjectForKey:(int32_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt64 -> UInt32
+/**
+ * Class used for map fields of <uint64_t, uint32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt64UInt32Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithUInt32:(uint32_t)value
forKey:(uint64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithUInt32s:(const uint32_t [])values
forKeys:(const uint64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithUInt32s:(const uint32_t [])values
forKeys:(const uint64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(uint64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndUInt32sUsingBlock:
(void (^)(uint64_t key, uint32_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBUInt64UInt32Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setUInt32:(uint32_t)value forKey:(uint64_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeUInt32ForKey:(uint64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt64 -> Int32
+/**
+ * Class used for map fields of <uint64_t, int32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt64Int32Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithInt32:(int32_t)value
forKey:(uint64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithInt32s:(const int32_t [])values
forKeys:(const uint64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt64Int32Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithInt32s:(const int32_t [])values
forKeys:(const uint64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBUInt64Int32Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getInt32:(nullable int32_t *)value forKey:(uint64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndInt32sUsingBlock:
(void (^)(uint64_t key, int32_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBUInt64Int32Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setInt32:(int32_t)value forKey:(uint64_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeInt32ForKey:(uint64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt64 -> UInt64
+/**
+ * Class used for map fields of <uint64_t, uint64_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt64UInt64Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithUInt64:(uint64_t)value
forKey:(uint64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithUInt64s:(const uint64_t [])values
forKeys:(const uint64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithUInt64s:(const uint64_t [])values
forKeys:(const uint64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(uint64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndUInt64sUsingBlock:
(void (^)(uint64_t key, uint64_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBUInt64UInt64Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setUInt64:(uint64_t)value forKey:(uint64_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeUInt64ForKey:(uint64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt64 -> Int64
+/**
+ * Class used for map fields of <uint64_t, int64_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt64Int64Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithInt64:(int64_t)value
forKey:(uint64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithInt64s:(const int64_t [])values
forKeys:(const uint64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt64Int64Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithInt64s:(const int64_t [])values
forKeys:(const uint64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBUInt64Int64Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getInt64:(nullable int64_t *)value forKey:(uint64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndInt64sUsingBlock:
(void (^)(uint64_t key, int64_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBUInt64Int64Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setInt64:(int64_t)value forKey:(uint64_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeInt64ForKey:(uint64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt64 -> Bool
+/**
+ * Class used for map fields of <uint64_t, BOOL>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt64BoolDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithBool:(BOOL)value
forKey:(uint64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithBools:(const BOOL [])values
forKeys:(const uint64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt64BoolDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithBools:(const BOOL [])values
forKeys:(const uint64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBUInt64BoolDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getBool:(nullable BOOL *)value forKey:(uint64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndBoolsUsingBlock:
(void (^)(uint64_t key, BOOL value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBUInt64BoolDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setBool:(BOOL)value forKey:(uint64_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeBoolForKey:(uint64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt64 -> Float
+/**
+ * Class used for map fields of <uint64_t, float>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt64FloatDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithFloat:(float)value
forKey:(uint64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithFloats:(const float [])values
forKeys:(const uint64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt64FloatDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithFloats:(const float [])values
forKeys:(const uint64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBUInt64FloatDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getFloat:(nullable float *)value forKey:(uint64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndFloatsUsingBlock:
(void (^)(uint64_t key, float value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBUInt64FloatDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setFloat:(float)value forKey:(uint64_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeFloatForKey:(uint64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt64 -> Double
+/**
+ * Class used for map fields of <uint64_t, double>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt64DoubleDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithDouble:(double)value
forKey:(uint64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithDoubles:(const double [])values
forKeys:(const uint64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt64DoubleDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithDoubles:(const double [])values
forKeys:(const uint64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBUInt64DoubleDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getDouble:(nullable double *)value forKey:(uint64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndDoublesUsingBlock:
(void (^)(uint64_t key, double value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBUInt64DoubleDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setDouble:(double)value forKey:(uint64_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeDoubleForKey:(uint64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt64 -> Enum
+/**
+ * Class used for map fields of <uint64_t, int32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt64EnumDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/** The validation function to check if the enums are valid. */
@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given validation function.
+ *
+ * @param func The enum validation function for the dictionary.
+ *
+ * @return A newly instanced dictionary.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param rawValue The raw enum value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValue:(int32_t)rawValue
forKey:(uint64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param values The raw enum values values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValues:(const int32_t [])values
forKeys:(const uint64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt64EnumDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
capacity:(NSUInteger)numItems;
+/**
+ * Initializes a dictionary with the given validation function.
+ *
+ * @param func The enum validation function for the dictionary.
+ *
+ * @return A newly initialized dictionary.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+
+/**
+ * Initializes a dictionary with the entries given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param values The raw enum values values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly initialized dictionary with the keys and values in it.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValues:(const int32_t [])values
forKeys:(const uint64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly initialized dictionary with the entries from the given
+ * dictionary in it.
+ **/
- (instancetype)initWithDictionary:(GPBUInt64EnumDictionary *)dictionary;
+
+/**
+ * Initializes a dictionary with the given capacity.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly initialized dictionary with the given capacity.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
capacity:(NSUInteger)numItems;
@@ -1071,23 +3937,63 @@ NS_ASSUME_NONNULL_BEGIN
// is not a valid enumerator as defined by validationFunc. If the actual value is
// desired, use "raw" version of the method.
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getEnum:(nullable int32_t *)value forKey:(uint64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndEnumsUsingBlock:
(void (^)(uint64_t key, int32_t value, BOOL *stop))block;
-// These methods bypass the validationFunc to provide access to values that were not
-// known at the time the binary was compiled.
-
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the raw enum value for the given key.
+ *
+ * @note This method bypass the validationFunc to enable the access of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param rawValue Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(uint64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @note This method bypass the validationFunc to enable the access of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **rawValue**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndRawValuesUsingBlock:
(void (^)(uint64_t key, int32_t rawValue, BOOL *stop))block;
+/**
+ * Adds the keys and raw enum values from another dictionary.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addRawEntriesFromDictionary:(GPBUInt64EnumDictionary *)otherDictionary;
// If value is not a valid enumerator as defined by validationFunc, these
@@ -1095,339 +4001,1312 @@ NS_ASSUME_NONNULL_BEGIN
// to the default value. Use the rawValue methods below to assign non enumerator
// values.
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setEnum:(int32_t)value forKey:(uint64_t)key;
-// This method bypass the validationFunc to provide setting of values that were not
-// known at the time the binary was compiled.
+/**
+ * Sets the raw enum value for the given key.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param rawValue The raw enum value to set.
+ * @param key The key under which to store the raw enum value.
+ **/
- (void)setRawValue:(int32_t)rawValue forKey:(uint64_t)key;
-// No validation applies to these methods.
-
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeEnumForKey:(uint64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - UInt64 -> Object
+/**
+ * Class used for map fields of <uint64_t, ObjectType>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBUInt64ObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param object The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithObject:(ObjectType)object
forKey:(uint64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param objects The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
forKeys:(const uint64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBUInt64ObjectDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param objects The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
forKeys:(const uint64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBUInt64ObjectDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
+/**
+ * Fetches the object stored under the given key.
+ *
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return The object if found, nil otherwise.
+ **/
- (ObjectType)objectForKey:(uint64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **object**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndObjectsUsingBlock:
(void (^)(uint64_t key, ObjectType object, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBUInt64ObjectDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param object The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setObject:(ObjectType)object forKey:(uint64_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeObjectForKey:(uint64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int64 -> UInt32
+/**
+ * Class used for map fields of <int64_t, uint32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt64UInt32Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithUInt32:(uint32_t)value
forKey:(int64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithUInt32s:(const uint32_t [])values
forKeys:(const int64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt64UInt32Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithUInt32s:(const uint32_t [])values
forKeys:(const int64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBInt64UInt32Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(int64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndUInt32sUsingBlock:
(void (^)(int64_t key, uint32_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBInt64UInt32Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setUInt32:(uint32_t)value forKey:(int64_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeUInt32ForKey:(int64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int64 -> Int32
+/**
+ * Class used for map fields of <int64_t, int32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt64Int32Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithInt32:(int32_t)value
forKey:(int64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithInt32s:(const int32_t [])values
forKeys:(const int64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt64Int32Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithInt32s:(const int32_t [])values
forKeys:(const int64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBInt64Int32Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getInt32:(nullable int32_t *)value forKey:(int64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndInt32sUsingBlock:
(void (^)(int64_t key, int32_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBInt64Int32Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setInt32:(int32_t)value forKey:(int64_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeInt32ForKey:(int64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int64 -> UInt64
+/**
+ * Class used for map fields of <int64_t, uint64_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt64UInt64Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithUInt64:(uint64_t)value
forKey:(int64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithUInt64s:(const uint64_t [])values
forKeys:(const int64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt64UInt64Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithUInt64s:(const uint64_t [])values
forKeys:(const int64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBInt64UInt64Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(int64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndUInt64sUsingBlock:
(void (^)(int64_t key, uint64_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBInt64UInt64Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setUInt64:(uint64_t)value forKey:(int64_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeUInt64ForKey:(int64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int64 -> Int64
+/**
+ * Class used for map fields of <int64_t, int64_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt64Int64Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithInt64:(int64_t)value
forKey:(int64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithInt64s:(const int64_t [])values
forKeys:(const int64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt64Int64Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithInt64s:(const int64_t [])values
forKeys:(const int64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBInt64Int64Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getInt64:(nullable int64_t *)value forKey:(int64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndInt64sUsingBlock:
(void (^)(int64_t key, int64_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBInt64Int64Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setInt64:(int64_t)value forKey:(int64_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeInt64ForKey:(int64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int64 -> Bool
+/**
+ * Class used for map fields of <int64_t, BOOL>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt64BoolDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithBool:(BOOL)value
forKey:(int64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithBools:(const BOOL [])values
forKeys:(const int64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt64BoolDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithBools:(const BOOL [])values
forKeys:(const int64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBInt64BoolDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getBool:(nullable BOOL *)value forKey:(int64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndBoolsUsingBlock:
(void (^)(int64_t key, BOOL value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBInt64BoolDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setBool:(BOOL)value forKey:(int64_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeBoolForKey:(int64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int64 -> Float
+/**
+ * Class used for map fields of <int64_t, float>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt64FloatDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithFloat:(float)value
forKey:(int64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithFloats:(const float [])values
forKeys:(const int64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt64FloatDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithFloats:(const float [])values
forKeys:(const int64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBInt64FloatDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getFloat:(nullable float *)value forKey:(int64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndFloatsUsingBlock:
(void (^)(int64_t key, float value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBInt64FloatDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setFloat:(float)value forKey:(int64_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeFloatForKey:(int64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int64 -> Double
+/**
+ * Class used for map fields of <int64_t, double>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt64DoubleDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithDouble:(double)value
forKey:(int64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithDoubles:(const double [])values
forKeys:(const int64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt64DoubleDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithDoubles:(const double [])values
forKeys:(const int64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBInt64DoubleDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getDouble:(nullable double *)value forKey:(int64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndDoublesUsingBlock:
(void (^)(int64_t key, double value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBInt64DoubleDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setDouble:(double)value forKey:(int64_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeDoubleForKey:(int64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int64 -> Enum
+/**
+ * Class used for map fields of <int64_t, int32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt64EnumDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/** The validation function to check if the enums are valid. */
@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given validation function.
+ *
+ * @param func The enum validation function for the dictionary.
+ *
+ * @return A newly instanced dictionary.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param rawValue The raw enum value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValue:(int32_t)rawValue
forKey:(int64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param values The raw enum values values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValues:(const int32_t [])values
forKeys:(const int64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt64EnumDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
capacity:(NSUInteger)numItems;
+/**
+ * Initializes a dictionary with the given validation function.
+ *
+ * @param func The enum validation function for the dictionary.
+ *
+ * @return A newly initialized dictionary.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+
+/**
+ * Initializes a dictionary with the entries given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param values The raw enum values values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly initialized dictionary with the keys and values in it.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValues:(const int32_t [])values
forKeys:(const int64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly initialized dictionary with the entries from the given
+ * dictionary in it.
+ **/
- (instancetype)initWithDictionary:(GPBInt64EnumDictionary *)dictionary;
+
+/**
+ * Initializes a dictionary with the given capacity.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly initialized dictionary with the given capacity.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
capacity:(NSUInteger)numItems;
@@ -1435,23 +5314,63 @@ NS_ASSUME_NONNULL_BEGIN
// is not a valid enumerator as defined by validationFunc. If the actual value is
// desired, use "raw" version of the method.
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getEnum:(nullable int32_t *)value forKey:(int64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndEnumsUsingBlock:
(void (^)(int64_t key, int32_t value, BOOL *stop))block;
-// These methods bypass the validationFunc to provide access to values that were not
-// known at the time the binary was compiled.
-
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the raw enum value for the given key.
+ *
+ * @note This method bypass the validationFunc to enable the access of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param rawValue Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(int64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @note This method bypass the validationFunc to enable the access of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **rawValue**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndRawValuesUsingBlock:
(void (^)(int64_t key, int32_t rawValue, BOOL *stop))block;
+/**
+ * Adds the keys and raw enum values from another dictionary.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addRawEntriesFromDictionary:(GPBInt64EnumDictionary *)otherDictionary;
// If value is not a valid enumerator as defined by validationFunc, these
@@ -1459,339 +5378,1312 @@ NS_ASSUME_NONNULL_BEGIN
// to the default value. Use the rawValue methods below to assign non enumerator
// values.
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setEnum:(int32_t)value forKey:(int64_t)key;
-// This method bypass the validationFunc to provide setting of values that were not
-// known at the time the binary was compiled.
+/**
+ * Sets the raw enum value for the given key.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param rawValue The raw enum value to set.
+ * @param key The key under which to store the raw enum value.
+ **/
- (void)setRawValue:(int32_t)rawValue forKey:(int64_t)key;
-// No validation applies to these methods.
-
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeEnumForKey:(int64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Int64 -> Object
+/**
+ * Class used for map fields of <int64_t, ObjectType>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBInt64ObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param object The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithObject:(ObjectType)object
forKey:(int64_t)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param objects The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
forKeys:(const int64_t [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBInt64ObjectDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param objects The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
forKeys:(const int64_t [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBInt64ObjectDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
+/**
+ * Fetches the object stored under the given key.
+ *
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return The object if found, nil otherwise.
+ **/
- (ObjectType)objectForKey:(int64_t)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **object**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndObjectsUsingBlock:
(void (^)(int64_t key, ObjectType object, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBInt64ObjectDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param object The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setObject:(ObjectType)object forKey:(int64_t)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeObjectForKey:(int64_t)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Bool -> UInt32
+/**
+ * Class used for map fields of <BOOL, uint32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBBoolUInt32Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithUInt32:(uint32_t)value
forKey:(BOOL)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithUInt32s:(const uint32_t [])values
forKeys:(const BOOL [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBBoolUInt32Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithUInt32s:(const uint32_t [])values
forKeys:(const BOOL [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBBoolUInt32Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(BOOL)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndUInt32sUsingBlock:
(void (^)(BOOL key, uint32_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBBoolUInt32Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setUInt32:(uint32_t)value forKey:(BOOL)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeUInt32ForKey:(BOOL)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Bool -> Int32
+/**
+ * Class used for map fields of <BOOL, int32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBBoolInt32Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithInt32:(int32_t)value
forKey:(BOOL)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithInt32s:(const int32_t [])values
forKeys:(const BOOL [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBBoolInt32Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithInt32s:(const int32_t [])values
forKeys:(const BOOL [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBBoolInt32Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getInt32:(nullable int32_t *)value forKey:(BOOL)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndInt32sUsingBlock:
(void (^)(BOOL key, int32_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBBoolInt32Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setInt32:(int32_t)value forKey:(BOOL)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeInt32ForKey:(BOOL)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Bool -> UInt64
+/**
+ * Class used for map fields of <BOOL, uint64_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBBoolUInt64Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithUInt64:(uint64_t)value
forKey:(BOOL)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithUInt64s:(const uint64_t [])values
forKeys:(const BOOL [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBBoolUInt64Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithUInt64s:(const uint64_t [])values
forKeys:(const BOOL [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBBoolUInt64Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(BOOL)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndUInt64sUsingBlock:
(void (^)(BOOL key, uint64_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBBoolUInt64Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setUInt64:(uint64_t)value forKey:(BOOL)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeUInt64ForKey:(BOOL)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Bool -> Int64
+/**
+ * Class used for map fields of <BOOL, int64_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBBoolInt64Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithInt64:(int64_t)value
forKey:(BOOL)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithInt64s:(const int64_t [])values
forKeys:(const BOOL [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBBoolInt64Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithInt64s:(const int64_t [])values
forKeys:(const BOOL [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBBoolInt64Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getInt64:(nullable int64_t *)value forKey:(BOOL)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndInt64sUsingBlock:
(void (^)(BOOL key, int64_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBBoolInt64Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setInt64:(int64_t)value forKey:(BOOL)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeInt64ForKey:(BOOL)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Bool -> Bool
+/**
+ * Class used for map fields of <BOOL, BOOL>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBBoolBoolDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithBool:(BOOL)value
forKey:(BOOL)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithBools:(const BOOL [])values
forKeys:(const BOOL [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBBoolBoolDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithBools:(const BOOL [])values
forKeys:(const BOOL [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBBoolBoolDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getBool:(nullable BOOL *)value forKey:(BOOL)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndBoolsUsingBlock:
(void (^)(BOOL key, BOOL value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBBoolBoolDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setBool:(BOOL)value forKey:(BOOL)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeBoolForKey:(BOOL)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Bool -> Float
+/**
+ * Class used for map fields of <BOOL, float>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBBoolFloatDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithFloat:(float)value
forKey:(BOOL)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithFloats:(const float [])values
forKeys:(const BOOL [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBBoolFloatDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithFloats:(const float [])values
forKeys:(const BOOL [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBBoolFloatDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getFloat:(nullable float *)value forKey:(BOOL)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndFloatsUsingBlock:
(void (^)(BOOL key, float value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBBoolFloatDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setFloat:(float)value forKey:(BOOL)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeFloatForKey:(BOOL)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Bool -> Double
+/**
+ * Class used for map fields of <BOOL, double>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBBoolDoubleDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithDouble:(double)value
forKey:(BOOL)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithDoubles:(const double [])values
forKeys:(const BOOL [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBBoolDoubleDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithDoubles:(const double [])values
forKeys:(const BOOL [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBBoolDoubleDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getDouble:(nullable double *)value forKey:(BOOL)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndDoublesUsingBlock:
(void (^)(BOOL key, double value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBBoolDoubleDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setDouble:(double)value forKey:(BOOL)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeDoubleForKey:(BOOL)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Bool -> Enum
+/**
+ * Class used for map fields of <BOOL, int32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBBoolEnumDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/** The validation function to check if the enums are valid. */
@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given validation function.
+ *
+ * @param func The enum validation function for the dictionary.
+ *
+ * @return A newly instanced dictionary.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param rawValue The raw enum value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValue:(int32_t)rawValue
forKey:(BOOL)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param values The raw enum values values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValues:(const int32_t [])values
forKeys:(const BOOL [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBBoolEnumDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
capacity:(NSUInteger)numItems;
+/**
+ * Initializes a dictionary with the given validation function.
+ *
+ * @param func The enum validation function for the dictionary.
+ *
+ * @return A newly initialized dictionary.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+
+/**
+ * Initializes a dictionary with the entries given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param values The raw enum values values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly initialized dictionary with the keys and values in it.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValues:(const int32_t [])values
forKeys:(const BOOL [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly initialized dictionary with the entries from the given
+ * dictionary in it.
+ **/
- (instancetype)initWithDictionary:(GPBBoolEnumDictionary *)dictionary;
+
+/**
+ * Initializes a dictionary with the given capacity.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly initialized dictionary with the given capacity.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
capacity:(NSUInteger)numItems;
@@ -1799,23 +6691,63 @@ NS_ASSUME_NONNULL_BEGIN
// is not a valid enumerator as defined by validationFunc. If the actual value is
// desired, use "raw" version of the method.
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getEnum:(nullable int32_t *)value forKey:(BOOL)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndEnumsUsingBlock:
(void (^)(BOOL key, int32_t value, BOOL *stop))block;
-// These methods bypass the validationFunc to provide access to values that were not
-// known at the time the binary was compiled.
-
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the raw enum value for the given key.
+ *
+ * @note This method bypass the validationFunc to enable the access of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param rawValue Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(BOOL)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @note This method bypass the validationFunc to enable the access of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **rawValue**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndRawValuesUsingBlock:
(void (^)(BOOL key, int32_t rawValue, BOOL *stop))block;
+/**
+ * Adds the keys and raw enum values from another dictionary.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addRawEntriesFromDictionary:(GPBBoolEnumDictionary *)otherDictionary;
// If value is not a valid enumerator as defined by validationFunc, these
@@ -1823,339 +6755,1312 @@ NS_ASSUME_NONNULL_BEGIN
// to the default value. Use the rawValue methods below to assign non enumerator
// values.
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setEnum:(int32_t)value forKey:(BOOL)key;
-// This method bypass the validationFunc to provide setting of values that were not
-// known at the time the binary was compiled.
+/**
+ * Sets the raw enum value for the given key.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param rawValue The raw enum value to set.
+ * @param key The key under which to store the raw enum value.
+ **/
- (void)setRawValue:(int32_t)rawValue forKey:(BOOL)key;
-// No validation applies to these methods.
-
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeEnumForKey:(BOOL)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - Bool -> Object
+/**
+ * Class used for map fields of <BOOL, ObjectType>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBBoolObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param object The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithObject:(ObjectType)object
forKey:(BOOL)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param objects The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
forKeys:(const BOOL [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBBoolObjectDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param objects The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
forKeys:(const BOOL [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBBoolObjectDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
+/**
+ * Fetches the object stored under the given key.
+ *
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return The object if found, nil otherwise.
+ **/
- (ObjectType)objectForKey:(BOOL)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **object**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndObjectsUsingBlock:
(void (^)(BOOL key, ObjectType object, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBBoolObjectDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param object The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setObject:(ObjectType)object forKey:(BOOL)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeObjectForKey:(BOOL)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - String -> UInt32
+/**
+ * Class used for map fields of <NSString, uint32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBStringUInt32Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithUInt32:(uint32_t)value
forKey:(NSString *)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithUInt32s:(const uint32_t [])values
forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBStringUInt32Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithUInt32s:(const uint32_t [])values
forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBStringUInt32Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getUInt32:(nullable uint32_t *)value forKey:(NSString *)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndUInt32sUsingBlock:
(void (^)(NSString *key, uint32_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBStringUInt32Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setUInt32:(uint32_t)value forKey:(NSString *)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeUInt32ForKey:(NSString *)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - String -> Int32
+/**
+ * Class used for map fields of <NSString, int32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBStringInt32Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithInt32:(int32_t)value
forKey:(NSString *)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithInt32s:(const int32_t [])values
forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBStringInt32Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithInt32s:(const int32_t [])values
forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBStringInt32Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getInt32:(nullable int32_t *)value forKey:(NSString *)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndInt32sUsingBlock:
(void (^)(NSString *key, int32_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBStringInt32Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setInt32:(int32_t)value forKey:(NSString *)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeInt32ForKey:(NSString *)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - String -> UInt64
+/**
+ * Class used for map fields of <NSString, uint64_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBStringUInt64Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithUInt64:(uint64_t)value
forKey:(NSString *)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithUInt64s:(const uint64_t [])values
forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBStringUInt64Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithUInt64s:(const uint64_t [])values
forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBStringUInt64Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getUInt64:(nullable uint64_t *)value forKey:(NSString *)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndUInt64sUsingBlock:
(void (^)(NSString *key, uint64_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBStringUInt64Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setUInt64:(uint64_t)value forKey:(NSString *)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeUInt64ForKey:(NSString *)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - String -> Int64
+/**
+ * Class used for map fields of <NSString, int64_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBStringInt64Dictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithInt64:(int64_t)value
forKey:(NSString *)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithInt64s:(const int64_t [])values
forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBStringInt64Dictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithInt64s:(const int64_t [])values
forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBStringInt64Dictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getInt64:(nullable int64_t *)value forKey:(NSString *)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndInt64sUsingBlock:
(void (^)(NSString *key, int64_t value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBStringInt64Dictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setInt64:(int64_t)value forKey:(NSString *)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeInt64ForKey:(NSString *)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - String -> Bool
+/**
+ * Class used for map fields of <NSString, BOOL>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBStringBoolDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithBool:(BOOL)value
forKey:(NSString *)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithBools:(const BOOL [])values
forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBStringBoolDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithBools:(const BOOL [])values
forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBStringBoolDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getBool:(nullable BOOL *)value forKey:(NSString *)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndBoolsUsingBlock:
(void (^)(NSString *key, BOOL value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBStringBoolDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setBool:(BOOL)value forKey:(NSString *)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeBoolForKey:(NSString *)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - String -> Float
+/**
+ * Class used for map fields of <NSString, float>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBStringFloatDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithFloat:(float)value
forKey:(NSString *)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithFloats:(const float [])values
forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBStringFloatDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithFloats:(const float [])values
forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBStringFloatDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getFloat:(nullable float *)value forKey:(NSString *)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndFloatsUsingBlock:
(void (^)(NSString *key, float value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBStringFloatDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setFloat:(float)value forKey:(NSString *)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeFloatForKey:(NSString *)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - String -> Double
+/**
+ * Class used for map fields of <NSString, double>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBStringDoubleDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param value The value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithDouble:(double)value
forKey:(NSString *)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param values The values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithDoubles:(const double [])values
forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBStringDoubleDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+/**
+ * Initializes this dictionary, copying the given values and keys.
+ *
+ * @param values The values to be placed in this dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of elements to copy into the dictionary.
+ *
+ * @return A newly initialized dictionary with a copy of the values and keys.
+ **/
- (instancetype)initWithDoubles:(const double [])values
forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this dictionary, copying the entries from the given dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to this dictionary.
+ *
+ * @return A newly initialized dictionary with the entries of the given dictionary.
+ **/
- (instancetype)initWithDictionary:(GPBStringDoubleDictionary *)dictionary;
+
+/**
+ * Initializes this dictionary with the requested capacity.
+ *
+ * @param numItems Number of items needed for this dictionary.
+ *
+ * @return A newly initialized dictionary with the requested capacity.
+ **/
- (instancetype)initWithCapacity:(NSUInteger)numItems;
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getDouble:(nullable double *)value forKey:(NSString *)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndDoublesUsingBlock:
(void (^)(NSString *key, double value, BOOL *stop))block;
+/**
+ * Adds the keys and values from another dictionary.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addEntriesFromDictionary:(GPBStringDoubleDictionary *)otherDictionary;
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setDouble:(double)value forKey:(NSString *)key;
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeDoubleForKey:(NSString *)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
#pragma mark - String -> Enum
+/**
+ * Class used for map fields of <NSString, int32_t>
+ * values. This performs better than boxing into NSNumbers in NSDictionaries.
+ *
+ * @note This class is not meant to be subclassed.
+ **/
@interface GPBStringEnumDictionary : NSObject <NSCopying>
+/** Number of entries stored in this dictionary. */
@property(nonatomic, readonly) NSUInteger count;
+/** The validation function to check if the enums are valid. */
@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+/**
+ * @return A newly instanced and empty dictionary.
+ **/
+ (instancetype)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given validation function.
+ *
+ * @param func The enum validation function for the dictionary.
+ *
+ * @return A newly instanced dictionary.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+
+/**
+ * Creates and initializes a dictionary with the single entry given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param rawValue The raw enum value to be placed in the dictionary.
+ * @param key The key under which to store the value.
+ *
+ * @return A newly instanced dictionary with the key and value in it.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValue:(int32_t)rawValue
forKey:(NSString *)key;
+
+/**
+ * Creates and initializes a dictionary with the entries given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param values The raw enum values values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly instanced dictionary with the keys and values in it.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValues:(const int32_t [])values
forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
count:(NSUInteger)count;
+
+/**
+ * Creates and initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly instanced dictionary with the entries from the given
+ * dictionary in it.
+ **/
+ (instancetype)dictionaryWithDictionary:(GPBStringEnumDictionary *)dictionary;
+
+/**
+ * Creates and initializes a dictionary with the given capacity.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly instanced dictionary with the given capacity.
+ **/
+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
capacity:(NSUInteger)numItems;
+/**
+ * Initializes a dictionary with the given validation function.
+ *
+ * @param func The enum validation function for the dictionary.
+ *
+ * @return A newly initialized dictionary.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+
+/**
+ * Initializes a dictionary with the entries given.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param values The raw enum values values to be placed in the dictionary.
+ * @param keys The keys under which to store the values.
+ * @param count The number of entries to store in the dictionary.
+ *
+ * @return A newly initialized dictionary with the keys and values in it.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
rawValues:(const int32_t [])values
forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes a dictionary with the entries from the given.
+ * dictionary.
+ *
+ * @param dictionary Dictionary containing the entries to add to the dictionary.
+ *
+ * @return A newly initialized dictionary with the entries from the given
+ * dictionary in it.
+ **/
- (instancetype)initWithDictionary:(GPBStringEnumDictionary *)dictionary;
+
+/**
+ * Initializes a dictionary with the given capacity.
+ *
+ * @param func The enum validation function for the dictionary.
+ * @param numItems Capacity needed for the dictionary.
+ *
+ * @return A newly initialized dictionary with the given capacity.
+ **/
- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
capacity:(NSUInteger)numItems;
@@ -2163,23 +8068,63 @@ NS_ASSUME_NONNULL_BEGIN
// is not a valid enumerator as defined by validationFunc. If the actual value is
// desired, use "raw" version of the method.
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the value for the given key.
+ *
+ * @param value Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getEnum:(nullable int32_t *)value forKey:(NSString *)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **value**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndEnumsUsingBlock:
(void (^)(NSString *key, int32_t value, BOOL *stop))block;
-// These methods bypass the validationFunc to provide access to values that were not
-// known at the time the binary was compiled.
-
-// Returns YES/NO to indicate if the key was found or not, filling in the value
-// only when the key was found.
+/**
+ * Gets the raw enum value for the given key.
+ *
+ * @note This method bypass the validationFunc to enable the access of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param rawValue Pointer into which the value will be set, if found.
+ * @param key Key under which the value is stored, if present.
+ *
+ * @return YES if the key was found and the value was copied, NO otherwise.
+ **/
- (BOOL)getRawValue:(nullable int32_t *)rawValue forKey:(NSString *)key;
+/**
+ * Enumerates the keys and values on this dictionary with the given block.
+ *
+ * @note This method bypass the validationFunc to enable the access of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param block The block to enumerate with.
+ * **key**: The key for the current entry.
+ * **rawValue**: The value for the current entry
+ * **stop**: A pointer to a boolean that when set stops the enumeration.
+ **/
- (void)enumerateKeysAndRawValuesUsingBlock:
(void (^)(NSString *key, int32_t rawValue, BOOL *stop))block;
+/**
+ * Adds the keys and raw enum values from another dictionary.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param otherDictionary Dictionary containing entries to be added to this
+ * dictionary.
+ **/
- (void)addRawEntriesFromDictionary:(GPBStringEnumDictionary *)otherDictionary;
// If value is not a valid enumerator as defined by validationFunc, these
@@ -2187,15 +8132,35 @@ NS_ASSUME_NONNULL_BEGIN
// to the default value. Use the rawValue methods below to assign non enumerator
// values.
+/**
+ * Sets the value for the given key.
+ *
+ * @param value The value to set.
+ * @param key The key under which to store the value.
+ **/
- (void)setEnum:(int32_t)value forKey:(NSString *)key;
-// This method bypass the validationFunc to provide setting of values that were not
-// known at the time the binary was compiled.
+/**
+ * Sets the raw enum value for the given key.
+ *
+ * @note This method bypass the validationFunc to enable the setting of values that
+ * were not known at the time the binary was compiled.
+ *
+ * @param rawValue The raw enum value to set.
+ * @param key The key under which to store the raw enum value.
+ **/
- (void)setRawValue:(int32_t)rawValue forKey:(NSString *)key;
-// No validation applies to these methods.
-
+/**
+ * Removes the entry for the given key.
+ *
+ * @param aKey Key to be removed from this dictionary.
+ **/
- (void)removeEnumForKey:(NSString *)aKey;
+
+/**
+ * Removes all entries in this dictionary.
+ **/
- (void)removeAll;
@end
@@ -2228,10 +8193,23 @@ NS_ASSUME_NONNULL_END
//%PDDM-DEFINE DICTIONARY_POD_KEY_TO_OBJECT_INTERFACE(KEY_NAME, KEY_TYPE, VALUE_NAME, VALUE_TYPE)
//%DICTIONARY_COMMON_INTERFACE(KEY_NAME, KEY_TYPE, , POD, VALUE_NAME, VALUE_TYPE, OBJECT, Object, object)
//%PDDM-DEFINE VALUE_FOR_KEY_POD(KEY_TYPE, VALUE_TYPE, VNAME)
-//%// Returns YES/NO to indicate if the key was found or not, filling in the value
-//%// only when the key was found.
+//%/**
+//% * Gets the value for the given key.
+//% *
+//% * @param value Pointer into which the value will be set, if found.
+//% * @param key Key under which the value is stored, if present.
+//% *
+//% * @return YES if the key was found and the value was copied, NO otherwise.
+//% **/
//%- (BOOL)get##VNAME##:(nullable VALUE_TYPE *)value forKey:(KEY_TYPE)key;
//%PDDM-DEFINE VALUE_FOR_KEY_OBJECT(KEY_TYPE, VALUE_TYPE, VNAME)
+//%/**
+//% * Fetches the object stored under the given key.
+//% *
+//% * @param key Key under which the value is stored, if present.
+//% *
+//% * @return The object if found, nil otherwise.
+//% **/
//%- (VALUE_TYPE)objectForKey:(KEY_TYPE)key;
//%PDDM-DEFINE VALUE_FOR_KEY_Enum(KEY_TYPE, VALUE_TYPE, VNAME)
//%VALUE_FOR_KEY_POD(KEY_TYPE, VALUE_TYPE, VNAME)
@@ -2250,27 +8228,105 @@ NS_ASSUME_NONNULL_END
//%PDDM-DEFINE DICTIONARY_COMMON_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME, VNAME_VAR)
//%#pragma mark - KEY_NAME -> VALUE_NAME
//%
+//%/**
+//% * Class used for map fields of <##KEY_TYPE##, ##VALUE_TYPE##>
+//% * values. This performs better than boxing into NSNumbers in NSDictionaries.
+//% *
+//% * @note This class is not meant to be subclassed.
+//% **/
//%@interface DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) : NSObject <NSCopying>
//%
+//%/** Number of entries stored in this dictionary. */
//%@property(nonatomic, readonly) NSUInteger count;
//%
+//%/**
+//% * @return A newly instanced and empty dictionary.
+//% **/
//%+ (instancetype)dictionary;
+//%
+//%/**
+//% * Creates and initializes a dictionary with the single entry given.
+//% *
+//% * @param ##VNAME_VAR The value to be placed in the dictionary.
+//% * @param key ##VNAME_VAR$S## The key under which to store the value.
+//% *
+//% * @return A newly instanced dictionary with the key and value in it.
+//% **/
//%+ (instancetype)dictionaryWith##VNAME##:(VALUE_TYPE)##VNAME_VAR
//% ##VNAME$S## forKey:(KEY_TYPE##KisP$S##KisP)key;
+//%
+//%/**
+//% * Creates and initializes a dictionary with the entries given.
+//% *
+//% * @param ##VNAME_VAR##s The values to be placed in the dictionary.
+//% * @param keys ##VNAME_VAR$S## The keys under which to store the values.
+//% * @param count ##VNAME_VAR$S## The number of entries to store in the dictionary.
+//% *
+//% * @return A newly instanced dictionary with the keys and values in it.
+//% **/
//%+ (instancetype)dictionaryWith##VNAME##s:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[])##VNAME_VAR##s
//% ##VNAME$S## forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[])keys
//% ##VNAME$S## count:(NSUInteger)count;
+//%
+//%/**
+//% * Creates and initializes a dictionary with the entries from the given.
+//% * dictionary.
+//% *
+//% * @param dictionary Dictionary containing the entries to add to the dictionary.
+//% *
+//% * @return A newly instanced dictionary with the entries from the given
+//% * dictionary in it.
+//% **/
//%+ (instancetype)dictionaryWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary;
+//%
+//%/**
+//% * Creates and initializes a dictionary with the given capacity.
+//% *
+//% * @param numItems Capacity needed for the dictionary.
+//% *
+//% * @return A newly instanced dictionary with the given capacity.
+//% **/
//%+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
//%
+//%/**
+//% * Initializes this dictionary, copying the given values and keys.
+//% *
+//% * @param ##VNAME_VAR##s The values to be placed in this dictionary.
+//% * @param keys ##VNAME_VAR$S## The keys under which to store the values.
+//% * @param count ##VNAME_VAR$S## The number of elements to copy into the dictionary.
+//% *
+//% * @return A newly initialized dictionary with a copy of the values and keys.
+//% **/
//%- (instancetype)initWith##VNAME##s:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[])##VNAME_VAR##s
//% ##VNAME$S## forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[])keys
//% ##VNAME$S## count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+//%
+//%/**
+//% * Initializes this dictionary, copying the entries from the given dictionary.
+//% *
+//% * @param dictionary Dictionary containing the entries to add to this dictionary.
+//% *
+//% * @return A newly initialized dictionary with the entries of the given dictionary.
+//% **/
//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary;
+//%
+//%/**
+//% * Initializes this dictionary with the requested capacity.
+//% *
+//% * @param numItems Number of items needed for this dictionary.
+//% *
+//% * @return A newly initialized dictionary with the requested capacity.
+//% **/
//%- (instancetype)initWithCapacity:(NSUInteger)numItems;
//%
//%DICTIONARY_IMMUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME, VNAME_VAR)
//%
+//%/**
+//% * Adds the keys and values from another dictionary.
+//% *
+//% * @param otherDictionary Dictionary containing entries to be added to this
+//% * dictionary.
+//% **/
//%- (void)addEntriesFromDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)otherDictionary;
//%
//%DICTIONARY_MUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME, VNAME_VAR)
@@ -2283,30 +8339,126 @@ NS_ASSUME_NONNULL_END
//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_INTERFACE2(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, VHELPER)
//%#pragma mark - KEY_NAME -> VALUE_NAME
//%
+//%/**
+//% * Class used for map fields of <##KEY_TYPE##, ##VALUE_TYPE##>
+//% * values. This performs better than boxing into NSNumbers in NSDictionaries.
+//% *
+//% * @note This class is not meant to be subclassed.
+//% **/
//%@interface GPB##KEY_NAME##VALUE_NAME##Dictionary : NSObject <NSCopying>
//%
+//%/** Number of entries stored in this dictionary. */
//%@property(nonatomic, readonly) NSUInteger count;
+//%/** The validation function to check if the enums are valid. */
//%@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
//%
+//%/**
+//% * @return A newly instanced and empty dictionary.
+//% **/
//%+ (instancetype)dictionary;
+//%
+//%/**
+//% * Creates and initializes a dictionary with the given validation function.
+//% *
+//% * @param func The enum validation function for the dictionary.
+//% *
+//% * @return A newly instanced dictionary.
+//% **/
//%+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+//%
+//%/**
+//% * Creates and initializes a dictionary with the single entry given.
+//% *
+//% * @param func The enum validation function for the dictionary.
+//% * @param rawValue The raw enum value to be placed in the dictionary.
+//% * @param key The key under which to store the value.
+//% *
+//% * @return A newly instanced dictionary with the key and value in it.
+//% **/
//%+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
//% rawValue:(VALUE_TYPE)rawValue
//% forKey:(KEY_TYPE##KisP$S##KisP)key;
+//%
+//%/**
+//% * Creates and initializes a dictionary with the entries given.
+//% *
+//% * @param func The enum validation function for the dictionary.
+//% * @param values The raw enum values values to be placed in the dictionary.
+//% * @param keys The keys under which to store the values.
+//% * @param count The number of entries to store in the dictionary.
+//% *
+//% * @return A newly instanced dictionary with the keys and values in it.
+//% **/
//%+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
//% rawValues:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[])values
//% forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[])keys
//% count:(NSUInteger)count;
+//%
+//%/**
+//% * Creates and initializes a dictionary with the entries from the given.
+//% * dictionary.
+//% *
+//% * @param dictionary Dictionary containing the entries to add to the dictionary.
+//% *
+//% * @return A newly instanced dictionary with the entries from the given
+//% * dictionary in it.
+//% **/
//%+ (instancetype)dictionaryWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary;
+//%
+//%/**
+//% * Creates and initializes a dictionary with the given capacity.
+//% *
+//% * @param func The enum validation function for the dictionary.
+//% * @param numItems Capacity needed for the dictionary.
+//% *
+//% * @return A newly instanced dictionary with the given capacity.
+//% **/
//%+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func
//% capacity:(NSUInteger)numItems;
//%
+//%/**
+//% * Initializes a dictionary with the given validation function.
+//% *
+//% * @param func The enum validation function for the dictionary.
+//% *
+//% * @return A newly initialized dictionary.
+//% **/
//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func;
+//%
+//%/**
+//% * Initializes a dictionary with the entries given.
+//% *
+//% * @param func The enum validation function for the dictionary.
+//% * @param values The raw enum values values to be placed in the dictionary.
+//% * @param keys The keys under which to store the values.
+//% * @param count The number of entries to store in the dictionary.
+//% *
+//% * @return A newly initialized dictionary with the keys and values in it.
+//% **/
//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
//% rawValues:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[])values
//% forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[])keys
//% count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+//%
+//%/**
+//% * Initializes a dictionary with the entries from the given.
+//% * dictionary.
+//% *
+//% * @param dictionary Dictionary containing the entries to add to the dictionary.
+//% *
+//% * @return A newly initialized dictionary with the entries from the given
+//% * dictionary in it.
+//% **/
//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary;
+//%
+//%/**
+//% * Initializes a dictionary with the given capacity.
+//% *
+//% * @param func The enum validation function for the dictionary.
+//% * @param numItems Capacity needed for the dictionary.
+//% *
+//% * @return A newly initialized dictionary with the given capacity.
+//% **/
//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func
//% capacity:(NSUInteger)numItems;
//%
@@ -2316,16 +8468,42 @@ NS_ASSUME_NONNULL_END
//%
//%DICTIONARY_IMMUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, Enum, value)
//%
-//%// These methods bypass the validationFunc to provide access to values that were not
-//%// known at the time the binary was compiled.
-//%
-//%// Returns YES/NO to indicate if the key was found or not, filling in the value
-//%// only when the key was found.
+//%/**
+//% * Gets the raw enum value for the given key.
+//% *
+//% * @note This method bypass the validationFunc to enable the access of values that
+//% * were not known at the time the binary was compiled.
+//% *
+//% * @param rawValue Pointer into which the value will be set, if found.
+//% * @param key Key under which the value is stored, if present.
+//% *
+//% * @return YES if the key was found and the value was copied, NO otherwise.
+//% **/
//%- (BOOL)getRawValue:(nullable VALUE_TYPE *)rawValue forKey:(KEY_TYPE##KisP$S##KisP)key;
//%
+//%/**
+//% * Enumerates the keys and values on this dictionary with the given block.
+//% *
+//% * @note This method bypass the validationFunc to enable the access of values that
+//% * were not known at the time the binary was compiled.
+//% *
+//% * @param block The block to enumerate with.
+//% * **key**: The key for the current entry.
+//% * **rawValue**: The value for the current entry
+//% * **stop**: A pointer to a boolean that when set stops the enumeration.
+//% **/
//%- (void)enumerateKeysAndRawValuesUsingBlock:
//% (void (^)(KEY_TYPE KisP##key, VALUE_TYPE rawValue, BOOL *stop))block;
//%
+//%/**
+//% * Adds the keys and raw enum values from another dictionary.
+//% *
+//% * @note This method bypass the validationFunc to enable the setting of values that
+//% * were not known at the time the binary was compiled.
+//% *
+//% * @param otherDictionary Dictionary containing entries to be added to this
+//% * dictionary.
+//% **/
//%- (void)addRawEntriesFromDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)otherDictionary;
//%
//%// If value is not a valid enumerator as defined by validationFunc, these
@@ -2341,13 +8519,36 @@ NS_ASSUME_NONNULL_END
//%PDDM-DEFINE DICTIONARY_IMMUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME, VNAME_VAR)
//%VALUE_FOR_KEY_##VHELPER(KEY_TYPE##KisP$S##KisP, VALUE_TYPE, VNAME)
//%
+//%/**
+//% * Enumerates the keys and values on this dictionary with the given block.
+//% *
+//% * @param block The block to enumerate with.
+//% * **key**: ##VNAME_VAR$S## The key for the current entry.
+//% * **VNAME_VAR**: The value for the current entry
+//% * **stop**: ##VNAME_VAR$S## A pointer to a boolean that when set stops the enumeration.
+//% **/
//%- (void)enumerateKeysAnd##VNAME##sUsingBlock:
//% (void (^)(KEY_TYPE KisP##key, VALUE_TYPE VNAME_VAR, BOOL *stop))block;
//%PDDM-DEFINE DICTIONARY_MUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME, VNAME_VAR)
+//%/**
+//% * Sets the value for the given key.
+//% *
+//% * @param ##VNAME_VAR The value to set.
+//% * @param key ##VNAME_VAR$S## The key under which to store the value.
+//% **/
//%- (void)set##VNAME##:(VALUE_TYPE)##VNAME_VAR forKey:(KEY_TYPE##KisP$S##KisP)key;
//%DICTIONARY_EXTRA_MUTABLE_METHODS_##VHELPER(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE)
+//%/**
+//% * Removes the entry for the given key.
+//% *
+//% * @param aKey Key to be removed from this dictionary.
+//% **/
//%- (void)remove##VNAME##ForKey:(KEY_TYPE##KisP$S##KisP)aKey;
+//%
+//%/**
+//% * Removes all entries in this dictionary.
+//% **/
//%- (void)removeAll;
//%PDDM-DEFINE DICTIONARY_EXTRA_MUTABLE_METHODS_POD(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE)
@@ -2356,9 +8557,14 @@ NS_ASSUME_NONNULL_END
// Empty
//%PDDM-DEFINE DICTIONARY_EXTRA_MUTABLE_METHODS_Enum(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE)
//%
-//%// This method bypass the validationFunc to provide setting of values that were not
-//%// known at the time the binary was compiled.
+//%/**
+//% * Sets the raw enum value for the given key.
+//% *
+//% * @note This method bypass the validationFunc to enable the setting of values that
+//% * were not known at the time the binary was compiled.
+//% *
+//% * @param rawValue The raw enum value to set.
+//% * @param key The key under which to store the raw enum value.
+//% **/
//%- (void)setRawValue:(VALUE_TYPE)rawValue forKey:(KEY_TYPE##KisP$S##KisP)key;
//%
-//%// No validation applies to these methods.
-//%
diff --git a/objectivec/GPBExtensionRegistry.h b/objectivec/GPBExtensionRegistry.h
index 08a6472a..d79632d2 100644
--- a/objectivec/GPBExtensionRegistry.h
+++ b/objectivec/GPBExtensionRegistry.h
@@ -35,45 +35,50 @@
NS_ASSUME_NONNULL_BEGIN
-/// A table of known extensions, searchable by name or field number. When
-/// parsing a protocol message that might have extensions, you must provide a
-/// @c GPBExtensionRegistry in which you have registered any extensions that you
-/// want to be able to parse. Otherwise, those extensions will just be treated
-/// like unknown fields.
-///
-/// The @c *Root classes provide @c +extensionRegistry for the extensions defined
-/// in a given file *and* all files it imports. You can also create a
-/// @c GPBExtensionRegistry, and merge those registries to handle parsing
-/// extensions defined from non overlapping files.
-///
-/// @code
-/// GPBExtensionRegistry *registry =
-/// [[[MyProtoFileRoot extensionRegistry] copy] autorelease];
-/// [registry addExtension:[OtherMessage neededExtension]; // Not in MyProtoFile
-/// NSError *parseError = nil;
-/// MyMessage *msg = [MyMessage parseData:data
-/// extensionRegistry:registry
-/// error:&parseError];
-/// @endcode
+/**
+ * A table of known extensions, searchable by name or field number. When
+ * parsing a protocol message that might have extensions, you must provide a
+ * GPBExtensionRegistry in which you have registered any extensions that you
+ * want to be able to parse. Otherwise, those extensions will just be treated
+ * like unknown fields.
+ *
+ * The *Root classes provide `+extensionRegistry` for the extensions defined
+ * in a given file *and* all files it imports. You can also create a
+ * GPBExtensionRegistry, and merge those registries to handle parsing
+ * extensions defined from non overlapping files.
+ *
+ * ```
+ * GPBExtensionRegistry *registry = [[MyProtoFileRoot extensionRegistry] copy];
+ * [registry addExtension:[OtherMessage neededExtension]]; // Not in MyProtoFile
+ * NSError *parseError;
+ * MyMessage *msg = [MyMessage parseData:data extensionRegistry:registry error:&parseError];
+ * ```
+ **/
@interface GPBExtensionRegistry : NSObject<NSCopying>
-/// Add the given @c GPBExtensionDescriptor to this registry.
-///
-/// @param extension The extension description to add.
+/**
+ * Adds the given GPBExtensionDescriptor to this registry.
+ *
+ * @param extension The extension description to add.
+ **/
- (void)addExtension:(GPBExtensionDescriptor *)extension;
-/// Adds all the extensions from another registry to this registry.
-///
-/// @param registry The registry to merge into this registry.
+/**
+ * Adds all the extensions from another registry to this registry.
+ *
+ * @param registry The registry to merge into this registry.
+ **/
- (void)addExtensions:(GPBExtensionRegistry *)registry;
-/// Looks for the extension registered for the given field number on a given
-/// @c GPBDescriptor.
-///
-/// @param descriptor The descriptor to look for a registered extension on.
-/// @param fieldNumber The field number of an extension to look for.
-///
-/// @return The registered @c GPBExtensionDescripto or nil if none was found.
+/**
+ * Looks for the extension registered for the given field number on a given
+ * GPBDescriptor.
+ *
+ * @param descriptor The descriptor to look for a registered extension on.
+ * @param fieldNumber The field number of the extension to look for.
+ *
+ * @return The registered GPBExtensionDescriptor or nil if none was found.
+ **/
- (nullable GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor
fieldNumber:(NSInteger)fieldNumber;
diff --git a/objectivec/GPBMessage.h b/objectivec/GPBMessage.h
index 9608cdb0..0cb74f9f 100644
--- a/objectivec/GPBMessage.h
+++ b/objectivec/GPBMessage.h
@@ -44,282 +44,404 @@ NS_ASSUME_NONNULL_BEGIN
CF_EXTERN_C_BEGIN
-/// NSError domain used for errors.
+/** NSError domain used for errors. */
extern NSString *const GPBMessageErrorDomain;
-/// Error code for NSError with GPBMessageErrorDomain.
+/** Error codes for NSErrors originated in GPBMessage. */
typedef NS_ENUM(NSInteger, GPBMessageErrorCode) {
- /// Uncategorized error.
+ /** Uncategorized error. */
GPBMessageErrorCodeOther = -100,
- /// A message can't be serialized because it is missing required fields.
+ /** Message couldn't be serialized because it is missing required fields. */
GPBMessageErrorCodeMissingRequiredField = -101,
};
-/// Key under which the error's reason is stored inside the userInfo dictionary.
+/**
+ * Key under which the GPBMessage error's reason is stored inside the userInfo
+ * dictionary.
+ **/
extern NSString *const GPBErrorReasonKey;
CF_EXTERN_C_END
-/// Base class for all of the generated message classes.
+/**
+ * Base class that each generated message subclasses from.
+ **/
@interface GPBMessage : NSObject<NSSecureCoding, NSCopying>
-
-// NOTE: If you add a instance method/property to this class that may conflict
-// with methods declared in protos, you need to update objective_helpers.cc.
-// The main cases are methods that take no arguments, or setFoo:/hasFoo: type
-// methods.
-
-/// The unknown fields for this message.
-///
-/// Only messages from proto files declared with "proto2" syntax support unknown
-/// fields. For "proto3" syntax, any unknown fields found while parsing are
-/// dropped.
+
+// If you add an instance method/property to this class that may conflict with
+// fields declared in protos, you need to update objective_helpers.cc. The main
+// cases are methods that take no arguments, or setFoo:/hasFoo: type methods.
+
+/**
+ * The set of unknown fields for this message.
+ *
+ * Only messages from proto files declared with "proto2" syntax support unknown
+ * fields. For "proto3" syntax, any unknown fields found while parsing are
+ * dropped.
+ **/
@property(nonatomic, copy, nullable) GPBUnknownFieldSet *unknownFields;
-/// Are all required fields set in the message and all embedded messages.
+/**
+ * Whether the message, along with all submessages, have the required fields
+ * set. This is only applicable for files declared with "proto2" syntax, as
+ * there are no required fields for "proto3" syntax.
+ **/
@property(nonatomic, readonly, getter=isInitialized) BOOL initialized;
-/// Returns an autoreleased instance.
+/**
+ * @return An autoreleased message with the default values set.
+ **/
+ (instancetype)message;
-/// Creates a new instance by parsing the data. This method should be sent to
-/// the generated message class that the data should be interpreted as. If
-/// there is an error the method returns nil and the error is returned in
-/// errorPtr (when provided).
-///
-/// @note In DEBUG builds, the parsed message is checked to be sure all required
-/// fields were provided, and the parse will fail if some are missing.
-///
-/// @note The errors returned are likely coming from the domain and codes listed
-/// at the top of this file and GPBCodedInputStream.h.
-///
-/// @param data The data to parse.
-/// @param errorPtr An optional error pointer to fill in with a failure reason if
-/// the data can not be parsed.
-///
-/// @return A new instance of the class messaged.
+/**
+ * Creates a new instance by parsing the provided data. This method should be
+ * sent to the generated message class that the data should be interpreted as.
+ * If there is an error the method returns nil and the error is returned in
+ * errorPtr (when provided).
+ *
+ * @note In DEBUG builds, the parsed message is checked to be sure all required
+ * fields were provided, and the parse will fail if some are missing.
+ *
+ * @note The errors returned are likely coming from the domain and codes listed
+ * at the top of this file and GPBCodedInputStream.h.
+ *
+ * @param data The data to parse.
+ * @param errorPtr An optional error pointer to fill in with a failure reason if
+ * the data can not be parsed.
+ *
+ * @return A new instance of the generated class.
+ **/
+ (nullable instancetype)parseFromData:(NSData *)data error:(NSError **)errorPtr;
-/// Creates a new instance by parsing the data. This method should be sent to
-/// the generated message class that the data should be interpreted as. If
-/// there is an error the method returns nil and the error is returned in
-/// errorPtr (when provided).
-///
-/// @note In DEBUG builds, the parsed message is checked to be sure all required
-/// fields were provided, and the parse will fail if some are missing.
-///
-/// @note The errors returned are likely coming from the domain and codes listed
-/// at the top of this file and GPBCodedInputStream.h.
-///
-/// @param data The data to parse.
-/// @param extensionRegistry The extension registry to use to look up extensions.
-/// @param errorPtr An optional error pointer to fill in with a failure
-/// reason if the data can not be parsed.
-///
-/// @return A new instance of the class messaged.
+/**
+ * Creates a new instance by parsing the data. This method should be sent to
+ * the generated message class that the data should be interpreted as. If
+ * there is an error the method returns nil and the error is returned in
+ * errorPtr (when provided).
+ *
+ * @note In DEBUG builds, the parsed message is checked to be sure all required
+ * fields were provided, and the parse will fail if some are missing.
+ *
+ * @note The errors returned are likely coming from the domain and codes listed
+ * at the top of this file and GPBCodedInputStream.h.
+ *
+ * @param data The data to parse.
+ * @param extensionRegistry The extension registry to use to look up extensions.
+ * @param errorPtr An optional error pointer to fill in with a failure
+ * reason if the data can not be parsed.
+ *
+ * @return A new instance of the generated class.
+ **/
+ (nullable instancetype)parseFromData:(NSData *)data
extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry
error:(NSError **)errorPtr;
-/// Creates a new instance by parsing the data from the given input stream. This
-/// method should be sent to the generated message class that the data should
-/// be interpreted as. If there is an error the method returns nil and the error
-/// is returned in errorPtr (when provided).
-///
-/// @note In DEBUG builds, the parsed message is checked to be sure all required
-/// fields were provided, and the parse will fail if some are missing.
-///
-/// @note The errors returned are likely coming from the domain and codes listed
-/// at the top of this file and GPBCodedInputStream.h.
-///
-/// @param input The stream to read data from.
-/// @param extensionRegistry The extension registry to use to look up extensions.
-/// @param errorPtr An optional error pointer to fill in with a failure
-/// reason if the data can not be parsed.
-///
-/// @return A new instance of the class messaged.
+/**
+ * Creates a new instance by parsing the data from the given input stream. This
+ * method should be sent to the generated message class that the data should
+ * be interpreted as. If there is an error the method returns nil and the error
+ * is returned in errorPtr (when provided).
+ *
+ * @note In DEBUG builds, the parsed message is checked to be sure all required
+ * fields were provided, and the parse will fail if some are missing.
+ *
+ * @note The errors returned are likely coming from the domain and codes listed
+ * at the top of this file and GPBCodedInputStream.h.
+ *
+ * @param input The stream to read data from.
+ * @param extensionRegistry The extension registry to use to look up extensions.
+ * @param errorPtr An optional error pointer to fill in with a failure
+ * reason if the data can not be parsed.
+ *
+ * @return A new instance of the generated class.
+ **/
+ (nullable instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input
extensionRegistry:
(nullable GPBExtensionRegistry *)extensionRegistry
error:(NSError **)errorPtr;
-/// Creates a new instance by parsing the data from the given input stream. This
-/// method should be sent to the generated message class that the data should
-/// be interpreted as. If there is an error the method returns nil and the error
-/// is returned in errorPtr (when provided).
-///
-/// @note Unlike the parseFrom... methods, this never checks to see if all of
-/// the required fields are set. So this method can be used to reload
-/// messages that may not be complete.
-///
-/// @note The errors returned are likely coming from the domain and codes listed
-/// at the top of this file and GPBCodedInputStream.h.
-///
-/// @param input The stream to read data from.
-/// @param extensionRegistry The extension registry to use to look up extensions.
-/// @param errorPtr An optional error pointer to fill in with a failure
-/// reason if the data can not be parsed.
-///
-/// @return A new instance of the class messaged.
+/**
+ * Creates a new instance by parsing the data from the given input stream. This
+ * method should be sent to the generated message class that the data should
+ * be interpreted as. If there is an error the method returns nil and the error
+ * is returned in errorPtr (when provided).
+ *
+ * @note Unlike the parseFrom... methods, this never checks to see if all of
+ * the required fields are set. So this method can be used to reload
+ * messages that may not be complete.
+ *
+ * @note The errors returned are likely coming from the domain and codes listed
+ * at the top of this file and GPBCodedInputStream.h.
+ *
+ * @param input The stream to read data from.
+ * @param extensionRegistry The extension registry to use to look up extensions.
+ * @param errorPtr An optional error pointer to fill in with a failure
+ * reason if the data can not be parsed.
+ *
+ * @return A new instance of the generated class.
+ **/
+ (nullable instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
extensionRegistry:
(nullable GPBExtensionRegistry *)extensionRegistry
error:(NSError **)errorPtr;
-/// Initializes an instance by parsing the data. This method should be sent to
-/// the generated message class that the data should be interpreted as. If
-/// there is an error the method returns nil and the error is returned in
-/// errorPtr (when provided).
-///
-/// @note In DEBUG builds, the parsed message is checked to be sure all required
-/// fields were provided, and the parse will fail if some are missing.
-///
-/// @note The errors returned are likely coming from the domain and codes listed
-/// at the top of this file and GPBCodedInputStream.h.
-///
-/// @param data The data to parse.
-/// @param errorPtr An optional error pointer to fill in with a failure reason if
-/// the data can not be parsed.
+/**
+ * Initializes an instance by parsing the data. This method should be sent to
+ * the generated message class that the data should be interpreted as. If
+ * there is an error the method returns nil and the error is returned in
+ * errorPtr (when provided).
+ *
+ * @note In DEBUG builds, the parsed message is checked to be sure all required
+ * fields were provided, and the parse will fail if some are missing.
+ *
+ * @note The errors returned are likely coming from the domain and codes listed
+ * at the top of this file and GPBCodedInputStream.h.
+ *
+ * @param data The data to parse.
+ * @param errorPtr An optional error pointer to fill in with a failure reason if
+ * the data can not be parsed.
+ *
+ * @return An initialized instance of the generated class.
+ **/
- (nullable instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr;
-/// Initializes an instance by parsing the data. This method should be sent to
-/// the generated message class that the data should be interpreted as. If
-/// there is an error the method returns nil and the error is returned in
-/// errorPtr (when provided).
-///
-/// @note In DEBUG builds, the parsed message is checked to be sure all required
-/// fields were provided, and the parse will fail if some are missing.
-///
-/// @note The errors returned are likely coming from the domain and codes listed
-/// at the top of this file and GPBCodedInputStream.h.
-///
-/// @param data The data to parse.
-/// @param extensionRegistry The extension registry to use to look up extensions.
-/// @param errorPtr An optional error pointer to fill in with a failure
-/// reason if the data can not be parsed.
+/**
+ * Initializes an instance by parsing the data. This method should be sent to
+ * the generated message class that the data should be interpreted as. If
+ * there is an error the method returns nil and the error is returned in
+ * errorPtr (when provided).
+ *
+ * @note In DEBUG builds, the parsed message is checked to be sure all required
+ * fields were provided, and the parse will fail if some are missing.
+ *
+ * @note The errors returned are likely coming from the domain and codes listed
+ * at the top of this file and GPBCodedInputStream.h.
+ *
+ * @param data The data to parse.
+ * @param extensionRegistry The extension registry to use to look up extensions.
+ * @param errorPtr An optional error pointer to fill in with a failure
+ * reason if the data can not be parsed.
+ *
+ * @return An initialized instance of the generated class.
+ **/
- (nullable instancetype)initWithData:(NSData *)data
extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry
error:(NSError **)errorPtr;
-/// Initializes an instance by parsing the data from the given input stream. This
-/// method should be sent to the generated message class that the data should
-/// be interpreted as. If there is an error the method returns nil and the error
-/// is returned in errorPtr (when provided).
-///
-/// @note Unlike the parseFrom... methods, this never checks to see if all of
-/// the required fields are set. So this method can be used to reload
-/// messages that may not be complete.
-///
-/// @note The errors returned are likely coming from the domain and codes listed
-/// at the top of this file and GPBCodedInputStream.h.
-///
-/// @param input The stream to read data from.
-/// @param extensionRegistry The extension registry to use to look up extensions.
-/// @param errorPtr An optional error pointer to fill in with a failure
-/// reason if the data can not be parsed.
+/**
+ * Initializes an instance by parsing the data from the given input stream. This
+ * method should be sent to the generated message class that the data should
+ * be interpreted as. If there is an error the method returns nil and the error
+ * is returned in errorPtr (when provided).
+ *
+ * @note Unlike the parseFrom... methods, this never checks to see if all of
+ * the required fields are set. So this method can be used to reload
+ * messages that may not be complete.
+ *
+ * @note The errors returned are likely coming from the domain and codes listed
+ * at the top of this file and GPBCodedInputStream.h.
+ *
+ * @param input The stream to read data from.
+ * @param extensionRegistry The extension registry to use to look up extensions.
+ * @param errorPtr An optional error pointer to fill in with a failure
+ * reason if the data can not be parsed.
+ *
+ * @return An initialized instance of the generated class.
+ **/
- (nullable instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input
extensionRegistry:
(nullable GPBExtensionRegistry *)extensionRegistry
error:(NSError **)errorPtr;
-/// Writes out the message to the given output stream.
+/**
+ * Parses the given data as this message's class, and merges those values into
+ * this message.
+ *
+ * @param data The binary representation of the message to merge.
+ * @param extensionRegistry The extension registry to use to look up extensions.
+ *
+ * @exception GPBCodedInputStreamException Exception thrown when parsing was
+ * unsuccessful.
+ **/
+- (void)mergeFromData:(NSData *)data
+ extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry;
+
+/**
+ * Merges the fields from another message (of the same type) into this
+ * message.
+ *
+ * @param other Message to merge into this message.
+ **/
+- (void)mergeFrom:(GPBMessage *)other;
+
+/**
+ * Writes out the message to the given coded output stream.
+ *
+ * @param output The coded output stream into which to write the message.
+ **/
- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output;
-/// Writes out the message to the given output stream.
+
+/**
+ * Writes out the message to the given output stream.
+ *
+ * @param output The output stream into which to write the message.
+ **/
- (void)writeToOutputStream:(NSOutputStream *)output;
-/// Writes out a varint for the message size followed by the the message to
-/// the given output stream.
+/**
+ * Writes out a varint for the message size followed by the the message to
+ * the given output stream.
+ *
+ * @param output The coded output stream into which to write the message.
+ **/
- (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output;
-/// Writes out a varint for the message size followed by the the message to
-/// the given output stream.
+
+/**
+ * Writes out a varint for the message size followed by the the message to
+ * the given output stream.
+ *
+ * @param output The output stream into which to write the message.
+ **/
- (void)writeDelimitedToOutputStream:(NSOutputStream *)output;
-/// Serializes the message to a @c NSData.
-///
-/// If there is an error while generating the data, nil is returned.
-///
-/// @note This value is not cached, so if you are using it repeatedly, cache
-/// it yourself.
-///
-/// @note In DEBUG ONLY, the message is also checked for all required field,
-/// if one is missing, nil will be returned.
+/**
+ * Serializes the message to an NSData.
+ *
+ * If there is an error while generating the data, nil is returned.
+ *
+ * @note This value is not cached, so if you are using it repeatedly, cache
+ * it yourself.
+ *
+ * @note In DEBUG ONLY, the message is also checked for all required field,
+ * if one is missing, nil will be returned.
+ *
+ * @return The binary representation of the message.
+ **/
- (nullable NSData *)data;
-/// Serializes a varint with the message size followed by the message data,
-/// returning that as a @c NSData.
-///
-/// @note This value is not cached, so if you are using it repeatedly, cache
-/// it yourself.
+/**
+ * Serializes a varint with the message size followed by the message data,
+ * returning that as an NSData.
+ *
+ * @note This value is not cached, so if you are using it repeatedly, it is
+ * recommended to keep a local copy.
+ *
+ * @return The binary representation of the size along with the message.
+ **/
- (NSData *)delimitedData;
-/// Calculates the size of the object if it were serialized.
-///
-/// This is not a cached value. If you are following a pattern like this:
-/// @code
-/// size_t size = [aMsg serializedSize];
-/// NSMutableData *foo = [NSMutableData dataWithCapacity:size + sizeof(size)];
-/// [foo writeSize:size];
-/// [foo appendData:[aMsg data]];
-/// @endcode
-/// you would be better doing:
-/// @code
-/// NSData *data = [aMsg data];
-/// NSUInteger size = [aMsg length];
-/// NSMutableData *foo = [NSMutableData dataWithCapacity:size + sizeof(size)];
-/// [foo writeSize:size];
-/// [foo appendData:data];
-/// @endcode
+/**
+ * Calculates the size of the object if it were serialized.
+ *
+ * This is not a cached value. If you are following a pattern like this:
+ *
+ * ```
+ * size_t size = [aMsg serializedSize];
+ * NSMutableData *foo = [NSMutableData dataWithCapacity:size + sizeof(size)];
+ * [foo writeSize:size];
+ * [foo appendData:[aMsg data]];
+ * ```
+ *
+ * you would be better doing:
+ *
+ * ```
+ * NSData *data = [aMsg data];
+ * NSUInteger size = [aMsg length];
+ * NSMutableData *foo = [NSMutableData dataWithCapacity:size + sizeof(size)];
+ * [foo writeSize:size];
+ * [foo appendData:data];
+ * ```
+ *
+ * @return The size of the message in it's binary representation.
+ **/
- (size_t)serializedSize;
-/// Return the descriptor for the message class.
+/**
+ * @return The descriptor for the message class.
+ **/
+ (GPBDescriptor *)descriptor;
-/// Return the descriptor for the message.
+
+/**
+ * Return the descriptor for the message.
+ **/
- (GPBDescriptor *)descriptor;
-/// Test to see if the given extension is set on the message.
+/**
+ * @return An array with the extension descriptors that are currently set on the
+ * message.
+ **/
+- (NSArray *)extensionsCurrentlySet;
+
+/**
+ * Checks whether there is an extension set on the message which matches the
+ * given extension descriptor.
+ *
+ * @param extension Extension descriptor to check if it's set on the message.
+ *
+ * @return Whether the extension is currently set on the message.
+ **/
- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension;
-/// Fetches the given extension's value for this message.
-///
-/// Extensions use boxed values (NSNumbers) for PODs and NSMutableArrays for
-/// repeated fields. If the extension is a Message one will be auto created for you
-/// and returned similar to fields.
+/*
+ * Fetches the given extension's value for this message.
+ *
+ * Extensions use boxed values (NSNumbers) for PODs and NSMutableArrays for
+ * repeated fields. If the extension is a Message one will be auto created for
+ * you and returned similar to fields.
+ *
+ * @param extension The extension descriptor of the extension to fetch.
+ *
+ * @return The extension matching the given descriptor, or nil if none found.
+ **/
- (nullable id)getExtension:(GPBExtensionDescriptor *)extension;
-/// Sets the given extension's value for this message. This is only for single
-/// field extensions (i.e. - not repeated fields).
-///
-/// Extensions use boxed values (@c NSNumbers).
-- (void)setExtension:(GPBExtensionDescriptor *)extension value:(nullable id)value;
-
-/// Adds the given value to the extension for this message. This is only for
-/// repeated field extensions. If the field is a repeated POD type the @c value
-/// is a @c NSNumber.
+/**
+ * Sets the given extension's value for this message. This only applies for
+ * single field extensions (i.e. - not repeated fields).
+ *
+ * Extensions use boxed values (NSNumbers).
+ *
+ * @param extension The extension descriptor under which to set the value.
+ * @param value The value to be set as the extension.
+ **/
+- (void)setExtension:(GPBExtensionDescriptor *)extension
+ value:(nullable id)value;
+
+/**
+ * Adds the given value to the extension for this message. This only applies
+ * to repeated field extensions. If the field is a repeated POD type, the value
+ * should be an NSNumber.
+ *
+ * @param extension The extension descriptor under which to add the value.
+ * @param value The value to be added to the repeated extension.
+ **/
- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value;
-/// Replaces the given value at an index for the extension on this message. This
-/// is only for repeated field extensions. If the field is a repeated POD type
-/// the @c value is a @c NSNumber.
+/**
+ * Replaces the value at the given index with the given value for the extension
+ * on this message. This only applies to repeated field extensions. If the field
+ * is a repeated POD type, the value is should be an NSNumber.
+ *
+ * @param extension The extension descriptor under which to replace the value.
+ * @param index The index of the extension to be replaced.
+ * @param value The value to be replaced in the repeated extension.
+ **/
- (void)setExtension:(GPBExtensionDescriptor *)extension
index:(NSUInteger)index
value:(id)value;
-/// Clears the given extension for this message.
+/**
+ * Clears the given extension for this message.
+ *
+ * @param extension The extension descriptor to be cleared from this message.
+ **/
- (void)clearExtension:(GPBExtensionDescriptor *)extension;
-/// Resets all of the fields of this message to their default values.
+/**
+ * Resets all of the fields of this message to their default values.
+ **/
- (void)clear;
-/// Parses a message of this type from the input and merges it with this
-/// message.
-///
-/// @note This will throw if there is an error parsing the data.
-- (void)mergeFromData:(NSData *)data
- extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry;
-
-/// Merges the fields from another message (of the same type) into this
-/// message.
-- (void)mergeFrom:(GPBMessage *)other;
-
@end
NS_ASSUME_NONNULL_END
diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m
index b9566bdf..4a6f0612 100644
--- a/objectivec/GPBMessage.m
+++ b/objectivec/GPBMessage.m
@@ -1777,11 +1777,6 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
}
}
-- (NSArray *)sortedExtensionsInUse {
- return [[extensionMap_ allKeys]
- sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
-}
-
- (void)setExtension:(GPBExtensionDescriptor *)extension value:(id)value {
if (!value) {
[self clearExtension:extension];
diff --git a/objectivec/GPBMessage_PackagePrivate.h b/objectivec/GPBMessage_PackagePrivate.h
index ff3cd6eb..02d0e16e 100644
--- a/objectivec/GPBMessage_PackagePrivate.h
+++ b/objectivec/GPBMessage_PackagePrivate.h
@@ -78,10 +78,6 @@ typedef struct GPBMessage_Storage *GPBMessage_StoragePtr;
// returns nil if the extension is not set)
- (id)getExistingExtension:(GPBExtensionDescriptor *)extension;
-// Returns an array of GPBExtensionDescriptor* for all the extensions currently
-// in use on the message. They are sorted by field number.
-- (NSArray *)sortedExtensionsInUse;
-
// Parses a message of this type from the input and merges it with this
// message.
//
diff --git a/objectivec/GPBRootObject.h b/objectivec/GPBRootObject.h
index c05b5c62..d2e2aebf 100644
--- a/objectivec/GPBRootObject.h
+++ b/objectivec/GPBRootObject.h
@@ -34,12 +34,17 @@
NS_ASSUME_NONNULL_BEGIN
-/// Every generated proto file defines a local "Root" class that exposes a
-/// @c GPBExtensionRegistry for all the extensions defined by that file and
-/// the files it depends on.
+/**
+ * Every generated proto file defines a local "Root" class that exposes a
+ * GPBExtensionRegistry for all the extensions defined by that file and
+ * the files it depends on.
+ **/
@interface GPBRootObject : NSObject
-/// An extension registry for the given file and all the files it depends on.
+/**
+ * @return An extension registry for the given file and all the files it depends
+ * on.
+ **/
+ (GPBExtensionRegistry *)extensionRegistry;
@end
diff --git a/objectivec/GPBRuntimeTypes.h b/objectivec/GPBRuntimeTypes.h
index 0a38b110..4d552060 100644
--- a/objectivec/GPBRuntimeTypes.h
+++ b/objectivec/GPBRuntimeTypes.h
@@ -36,21 +36,28 @@
@class GPBMessage;
@class GPBInt32Array;
-// Function used to verify that a given value can be represented by an
-// enum type.
+/**
+ * Verifies that a given value can be represented by an enum type.
+ * */
typedef BOOL (*GPBEnumValidationFunc)(int32_t);
-// Function used to fetch an EnumDescriptor.
+/**
+ * Fetches an EnumDescriptor.
+ * */
typedef GPBEnumDescriptor *(*GPBEnumDescriptorFunc)(void);
-// Magic values used for when an the at runtime to indicate an enum value
-// that wasn't know at compile time.
+/**
+ * Magic value used at runtime to indicate an enum value that wasn't know at
+ * compile time.
+ * */
enum {
kGPBUnrecognizedEnumeratorValue = (int32_t)0xFBADBEEF,
};
-// A union for storing all possible Protobuf values.
-// Note that owner is responsible for memory management of object types.
+/**
+ * A union for storing all possible Protobuf values. Note that owner is
+ * responsible for memory management of object types.
+ * */
typedef union {
BOOL valueBool;
int32_t valueInt32;
@@ -65,38 +72,73 @@ typedef union {
int32_t valueEnum;
} GPBGenericValue;
-// Do not change the order of this enum (or add things to it) without thinking
-// about it very carefully. There are several things that depend on the order.
+/**
+ * Enum listing the possible data types that a field can contain.
+ *
+ * @note Do not change the order of this enum (or add things to it) without
+ * thinking about it very carefully. There are several things that depend
+ * on the order.
+ * */
typedef NS_ENUM(uint8_t, GPBDataType) {
+ /** Field contains boolean value(s). */
GPBDataTypeBool = 0,
+ /** Field contains unsigned 4 byte value(s). */
GPBDataTypeFixed32,
+ /** Field contains signed 4 byte value(s). */
GPBDataTypeSFixed32,
+ /** Field contains float value(s). */
GPBDataTypeFloat,
+ /** Field contains unsigned 8 byte value(s). */
GPBDataTypeFixed64,
+ /** Field contains signed 8 byte value(s). */
GPBDataTypeSFixed64,
+ /** Field contains double value(s). */
GPBDataTypeDouble,
+ /**
+ * Field contains variable length value(s). Inefficient for encoding negative
+ * numbers – if your field is likely to have negative values, use
+ * GPBDataTypeSInt32 instead.
+ **/
GPBDataTypeInt32,
+ /**
+ * Field contains variable length value(s). Inefficient for encoding negative
+ * numbers – if your field is likely to have negative values, use
+ * GPBDataTypeSInt64 instead.
+ **/
GPBDataTypeInt64,
+ /** Field contains signed variable length integer value(s). */
GPBDataTypeSInt32,
+ /** Field contains signed variable length integer value(s). */
GPBDataTypeSInt64,
+ /** Field contains unsigned variable length integer value(s). */
GPBDataTypeUInt32,
+ /** Field contains unsigned variable length integer value(s). */
GPBDataTypeUInt64,
+ /** Field contains an arbitrary sequence of bytes. */
GPBDataTypeBytes,
+ /** Field contains UTF-8 encoded or 7-bit ASCII text. */
GPBDataTypeString,
+ /** Field contains message type(s). */
GPBDataTypeMessage,
+ /** Field contains message type(s). */
GPBDataTypeGroup,
+ /** Field contains enum value(s). */
GPBDataTypeEnum,
};
enum {
- // A count of the number of types in GPBDataType. Separated out from the
- // GPBDataType enum to avoid warnings regarding not handling
- // GPBDataType_Count in switch statements.
+ /**
+ * A count of the number of types in GPBDataType. Separated out from the
+ * GPBDataType enum to avoid warnings regarding not handling GPBDataType_Count
+ * in switch statements.
+ **/
GPBDataType_Count = GPBDataTypeEnum + 1
};
-// An extension range.
+/** An extension range. */
typedef struct GPBExtensionRange {
- uint32_t start; // inclusive
- uint32_t end; // exclusive
+ /** Inclusive. */
+ uint32_t start;
+ /** Exclusive. */
+ uint32_t end;
} GPBExtensionRange;
diff --git a/objectivec/GPBUnknownField.h b/objectivec/GPBUnknownField.h
index 0f301e47..a135cc20 100644
--- a/objectivec/GPBUnknownField.h
+++ b/objectivec/GPBUnknownField.h
@@ -36,52 +36,59 @@
@class GPBUnknownFieldSet;
NS_ASSUME_NONNULL_BEGIN
-
-/// Store an unknown field. These are used in conjunction with @c GPBUnknownFieldSet
+/**
+ * Store an unknown field. These are used in conjunction with
+ * GPBUnknownFieldSet.
+ **/
@interface GPBUnknownField : NSObject<NSCopying>
-/// The field number the data is stored under.
+/** The field number the data is stored under. */
@property(nonatomic, readonly, assign) int32_t number;
-/// An array of varint values for this field.
+/** An array of varint values for this field. */
@property(nonatomic, readonly, strong) GPBUInt64Array *varintList;
-/// An array of fixed32 values for this field.
+/** An array of fixed32 values for this field. */
@property(nonatomic, readonly, strong) GPBUInt32Array *fixed32List;
-/// An array of fixed64 values for this field.
+/** An array of fixed64 values for this field. */
@property(nonatomic, readonly, strong) GPBUInt64Array *fixed64List;
-/// An array of data values for this field.
+/** An array of data values for this field. */
@property(nonatomic, readonly, strong) NSArray<NSData*> *lengthDelimitedList;
-/// An array of groups of values for this field.
+/** An array of groups of values for this field. */
@property(nonatomic, readonly, strong) NSArray<GPBUnknownFieldSet*> *groupList;
-
-/// Add a value to the varintList.
-///
-/// @param value The value to add.
+/**
+ * Add a value to the varintList.
+ *
+ * @param value The value to add.
+ **/
- (void)addVarint:(uint64_t)value;
-
-/// Add a value to the fixed32List.
-///
-/// @param value The value to add.
+/**
+ * Add a value to the fixed32List.
+ *
+ * @param value The value to add.
+ **/
- (void)addFixed32:(uint32_t)value;
-
-/// Add a value to the fixed64List.
-///
-/// @param value The value to add.
+/**
+ * Add a value to the fixed64List.
+ *
+ * @param value The value to add.
+ **/
- (void)addFixed64:(uint64_t)value;
-
-/// Add a value to the lengthDelimitedList.
-///
-/// @param value The value to add.
+/**
+ * Add a value to the lengthDelimitedList.
+ *
+ * @param value The value to add.
+ **/
- (void)addLengthDelimited:(NSData *)value;
-
-/// Add a value to the groupList.
-///
-/// @param value The value to add.
+/**
+ * Add a value to the groupList.
+ *
+ * @param value The value to add.
+ **/
- (void)addGroup:(GPBUnknownFieldSet *)value;
@end
diff --git a/objectivec/GPBUnknownFieldSet.h b/objectivec/GPBUnknownFieldSet.h
index cf612993..1b5f24f3 100644
--- a/objectivec/GPBUnknownFieldSet.h
+++ b/objectivec/GPBUnknownFieldSet.h
@@ -34,31 +34,48 @@
NS_ASSUME_NONNULL_BEGIN
-/// A collection of unknown fields.
+/**
+ * A collection of unknown fields. Fields parsed from the binary representation
+ * of a message that are unknown end up in an instance of this set. This only
+ * applies for files declared with the "proto2" syntax. Files declared with the
+ * "proto3" syntax discard the unknown values.
+ **/
@interface GPBUnknownFieldSet : NSObject<NSCopying>
-/// Tests to see if the given field number has a value.
-///
-/// @param number The field number to check.
-///
-/// @return YES if there is an unknown field for the given field number.
+/**
+ * Tests to see if the given field number has a value.
+ *
+ * @param number The field number to check.
+ *
+ * @return YES if there is an unknown field for the given field number.
+ **/
- (BOOL)hasField:(int32_t)number;
-/// Fetches the @c GPBUnknownField for the given field number.
-///
-/// @param number The field number to look up.
-///
-/// @return The @c GPBUnknownField or nil.
+/**
+ * Fetches the GPBUnknownField for the given field number.
+ *
+ * @param number The field number to look up.
+ *
+ * @return The GPBUnknownField or nil if none found.
+ **/
- (nullable GPBUnknownField *)getField:(int32_t)number;
-/// Returns the number of fields in this set.
+/**
+ * @return The number of fields in this set.
+ **/
- (NSUInteger)countOfFields;
-/// Adds the given field to the set.
+/**
+ * Adds the given field to the set.
+ *
+ * @param field The field to add to the set.
+ **/
- (void)addField:(GPBUnknownField *)field;
-/// Returns an NSArray of the @c GPBUnknownFields sorted by the field numbers.
-- (NSArray<GPBUnknownField*> *)sortedFields;
+/**
+ * @return An array of the GPBUnknownFields sorted by the field numbers.
+ **/
+- (NSArray<GPBUnknownField *> *)sortedFields;
@end
diff --git a/objectivec/GPBUtilities.h b/objectivec/GPBUtilities.h
index b7209324..52e7d2e0 100644
--- a/objectivec/GPBUtilities.h
+++ b/objectivec/GPBUtilities.h
@@ -38,34 +38,58 @@ CF_EXTERN_C_BEGIN
NS_ASSUME_NONNULL_BEGIN
-/// Generates a string that should be a valid "Text Format" for the C++ version
-/// of Protocol Buffers.
-///
-/// @param message The message to generate from.
-/// @param lineIndent A string to use as the prefix for all lines generated. Can
-/// be nil if no extra indent is needed.
-///
-/// @return A @c NSString with the Text Format of the message.
+/**
+ * Generates a string that should be a valid "TextFormat" for the C++ version
+ * of Protocol Buffers.
+ *
+ * @param message The message to generate from.
+ * @param lineIndent A string to use as the prefix for all lines generated. Can
+ * be nil if no extra indent is needed.
+ *
+ * @return An NSString with the TextFormat of the message.
+ **/
NSString *GPBTextFormatForMessage(GPBMessage *message,
NSString * __nullable lineIndent);
-/// Generates a string that should be a valid "Text Format" for the C++ version
-/// of Protocol Buffers.
-///
-/// @param unknownSet The unknown field set to generate from.
-/// @param lineIndent A string to use as the prefix for all lines generated. Can
-/// be nil if no extra indent is needed.
-///
-/// @return A @c NSString with the Text Format of the unknown field set.
+/**
+ * Generates a string that should be a valid "TextFormat" for the C++ version
+ * of Protocol Buffers.
+ *
+ * @param unknownSet The unknown field set to generate from.
+ * @param lineIndent A string to use as the prefix for all lines generated. Can
+ * be nil if no extra indent is needed.
+ *
+ * @return An NSString with the TextFormat of the unknown field set.
+ **/
NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet * __nullable unknownSet,
NSString * __nullable lineIndent);
-/// Test if the given field is set on a message.
+/**
+ * Checks if the given field number is set on a message.
+ *
+ * @param self The message to check.
+ * @param fieldNumber The field number to check.
+ *
+ * @return YES if the field number is set on the given message.
+ **/
BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber);
-/// Test if the given field is set on a message.
+
+/**
+ * Checks if the given field is set on a message.
+ *
+ * @param self The message to check.
+ * @param field The field to check.
+ *
+ * @return YES if the field is set on the given message.
+ **/
BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field);
-/// Clear the given field of a message.
+/**
+ * Clears the given field for the given message.
+ *
+ * @param self The message for which to clear the field.
+ * @param field The field to clear.
+ **/
void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field);
//%PDDM-EXPAND GPB_ACCESSORS()
@@ -73,112 +97,299 @@ void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field);
//
-// Get/Set the given field of a message.
+// Get/Set a given field from/to a message.
//
// Single Fields
-/// Gets the value of a bytes field.
+/**
+ * Gets the value of a bytes field.
+ *
+ * @param self The message from which to get the field.
+ * @param field The field to get.
+ **/
NSData *GPBGetMessageBytesField(GPBMessage *self, GPBFieldDescriptor *field);
-/// Sets the value of a bytes field.
+
+/**
+ * Sets the value of a bytes field.
+ *
+ * @param self The message into which to set the field.
+ * @param field The field to set.
+ * @param value The to set in the field.
+ **/
void GPBSetMessageBytesField(GPBMessage *self, GPBFieldDescriptor *field, NSData *value);
-/// Gets the value of a string field.
+/**
+ * Gets the value of a string field.
+ *
+ * @param self The message from which to get the field.
+ * @param field The field to get.
+ **/
NSString *GPBGetMessageStringField(GPBMessage *self, GPBFieldDescriptor *field);
-/// Sets the value of a string field.
+
+/**
+ * Sets the value of a string field.
+ *
+ * @param self The message into which to set the field.
+ * @param field The field to set.
+ * @param value The to set in the field.
+ **/
void GPBSetMessageStringField(GPBMessage *self, GPBFieldDescriptor *field, NSString *value);
-/// Gets the value of a message field.
+/**
+ * Gets the value of a message field.
+ *
+ * @param self The message from which to get the field.
+ * @param field The field to get.
+ **/
GPBMessage *GPBGetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field);
-/// Sets the value of a message field.
+
+/**
+ * Sets the value of a message field.
+ *
+ * @param self The message into which to set the field.
+ * @param field The field to set.
+ * @param value The to set in the field.
+ **/
void GPBSetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field, GPBMessage *value);
-/// Gets the value of a group field.
+/**
+ * Gets the value of a group field.
+ *
+ * @param self The message from which to get the field.
+ * @param field The field to get.
+ **/
GPBMessage *GPBGetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field);
-/// Sets the value of a group field.
+
+/**
+ * Sets the value of a group field.
+ *
+ * @param self The message into which to set the field.
+ * @param field The field to set.
+ * @param value The to set in the field.
+ **/
void GPBSetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field, GPBMessage *value);
-/// Gets the value of a bool field.
+/**
+ * Gets the value of a bool field.
+ *
+ * @param self The message from which to get the field.
+ * @param field The field to get.
+ **/
BOOL GPBGetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field);
-/// Sets the value of a bool field.
+
+/**
+ * Sets the value of a bool field.
+ *
+ * @param self The message into which to set the field.
+ * @param field The field to set.
+ * @param value The to set in the field.
+ **/
void GPBSetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field, BOOL value);
-/// Gets the value of an int32 field.
+/**
+ * Gets the value of an int32 field.
+ *
+ * @param self The message from which to get the field.
+ * @param field The field to get.
+ **/
int32_t GPBGetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field);
-/// Sets the value of an int32 field.
+
+/**
+ * Sets the value of an int32 field.
+ *
+ * @param self The message into which to set the field.
+ * @param field The field to set.
+ * @param value The to set in the field.
+ **/
void GPBSetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field, int32_t value);
-/// Gets the value of an uint32 field.
+/**
+ * Gets the value of an uint32 field.
+ *
+ * @param self The message from which to get the field.
+ * @param field The field to get.
+ **/
uint32_t GPBGetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field);
-/// Sets the value of an uint32 field.
+
+/**
+ * Sets the value of an uint32 field.
+ *
+ * @param self The message into which to set the field.
+ * @param field The field to set.
+ * @param value The to set in the field.
+ **/
void GPBSetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field, uint32_t value);
-/// Gets the value of an int64 field.
+/**
+ * Gets the value of an int64 field.
+ *
+ * @param self The message from which to get the field.
+ * @param field The field to get.
+ **/
int64_t GPBGetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field);
-/// Sets the value of an int64 field.
+
+/**
+ * Sets the value of an int64 field.
+ *
+ * @param self The message into which to set the field.
+ * @param field The field to set.
+ * @param value The to set in the field.
+ **/
void GPBSetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field, int64_t value);
-/// Gets the value of an uint64 field.
+/**
+ * Gets the value of an uint64 field.
+ *
+ * @param self The message from which to get the field.
+ * @param field The field to get.
+ **/
uint64_t GPBGetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field);
-/// Sets the value of an uint64 field.
+
+/**
+ * Sets the value of an uint64 field.
+ *
+ * @param self The message into which to set the field.
+ * @param field The field to set.
+ * @param value The to set in the field.
+ **/
void GPBSetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field, uint64_t value);
-/// Gets the value of a float field.
+/**
+ * Gets the value of a float field.
+ *
+ * @param self The message from which to get the field.
+ * @param field The field to get.
+ **/
float GPBGetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field);
-/// Sets the value of a float field.
+
+/**
+ * Sets the value of a float field.
+ *
+ * @param self The message into which to set the field.
+ * @param field The field to set.
+ * @param value The to set in the field.
+ **/
void GPBSetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field, float value);
-/// Gets the value of a double field.
+/**
+ * Gets the value of a double field.
+ *
+ * @param self The message from which to get the field.
+ * @param field The field to get.
+ **/
double GPBGetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field);
-/// Sets the value of a double field.
+
+/**
+ * Sets the value of a double field.
+ *
+ * @param self The message into which to set the field.
+ * @param field The field to set.
+ * @param value The to set in the field.
+ **/
void GPBSetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field, double value);
-/// Get the given enum field of a message. For proto3, if the value isn't a
-/// member of the enum, @c kGPBUnrecognizedEnumeratorValue will be returned.
-/// GPBGetMessageRawEnumField will bypass the check and return whatever value
-/// was set.
+/**
+ * Gets the given enum field of a message. For proto3, if the value isn't a
+ * member of the enum, @c kGPBUnrecognizedEnumeratorValue will be returned.
+ * GPBGetMessageRawEnumField will bypass the check and return whatever value
+ * was set.
+ *
+ * @param self The message from which to get the field.
+ * @param field The field to get.
+ *
+ * @return The enum value for the given field.
+ **/
int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field);
-/// Set the given enum field of a message. You can only set values that are
-/// members of the enum.
-void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value);
-/// Get the given enum field of a message. No check is done to ensure the value
-/// was defined in the enum.
+
+/**
+ * Set the given enum field of a message. You can only set values that are
+ * members of the enum.
+ *
+ * @param self The message into which to set the field.
+ * @param field The field to set.
+ * @param value The enum value to set in the field.
+ **/
+void GPBSetMessageEnumField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int32_t value);
+
+/**
+ * Get the given enum field of a message. No check is done to ensure the value
+ * was defined in the enum.
+ *
+ * @param self The message from which to get the field.
+ * @param field The field to get.
+ *
+ * @return The raw enum value for the given field.
+ **/
int32_t GPBGetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field);
-/// Set the given enum field of a message. You can set the value to anything,
-/// even a value that is not a member of the enum.
-void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value);
+
+/**
+ * Set the given enum field of a message. You can set the value to anything,
+ * even a value that is not a member of the enum.
+ *
+ * @param self The message into which to set the field.
+ * @param field The field to set.
+ * @param value The raw enum value to set in the field.
+ **/
+void GPBSetMessageRawEnumField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int32_t value);
// Repeated Fields
-/// Gets the value of a repeated field.
-///
-/// The result will be @c GPB*Array or @c NSMutableArray based on the
-/// field's type.
+/**
+ * Gets the value of a repeated field.
+ *
+ * @param self The message from which to get the field.
+ * @param field The repeated field to get.
+ *
+ * @return A GPB*Array or an NSMutableArray based on the field's type.
+ **/
id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field);
-/// Sets the value of a repeated field.
-///
-/// The value should be @c GPB*Array or @c NSMutableArray based on the
-/// field's type.
-void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array);
+
+/**
+ * Sets the value of a repeated field.
+ *
+ * @param self The message into which to set the field.
+ * @param field The field to set.
+ * @param array A GPB*Array or NSMutableArray based on the field's type.
+ **/
+void GPBSetMessageRepeatedField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ id array);
// Map Fields
-/// Gets the value of a map<> field.
-///
-/// The result will be @c GPB*Dictionary or @c NSMutableDictionary based on
-/// the field's type.
+/**
+ * Gets the value of a map<> field.
+ *
+ * @param self The message from which to get the field.
+ * @param field The repeated field to get.
+ *
+ * @return A GPB*Dictionary or NSMutableDictionary based on the field's type.
+ **/
id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field);
-/// Sets the value of a map<> field.
-///
-/// The object should be @c GPB*Dictionary or @c NSMutableDictionary based
-/// on the field's type.
-void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, id dictionary);
+
+/**
+ * Sets the value of a map<> field.
+ *
+ * @param self The message into which to set the field.
+ * @param field The field to set.
+ * @param dictionary A GPB*Dictionary or NSMutableDictionary based on the
+ * field's type.
+ **/
+void GPBSetMessageMapField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ id dictionary);
//%PDDM-EXPAND-END GPB_ACCESSORS()
-// Returns an empty NSData to assign to byte fields when you wish
-// to assign them to empty. Prevents allocating a lot of little [NSData data]
-// objects.
+/**
+ * Returns an empty NSData to assign to byte fields when you wish to assign them
+ * to empty. Prevents allocating a lot of little [NSData data] objects.
+ **/
NSData *GPBEmptyNSData(void) __attribute__((pure));
NS_ASSUME_NONNULL_END
@@ -189,7 +400,7 @@ CF_EXTERN_C_END
//%PDDM-DEFINE GPB_ACCESSORS()
//%
//%//
-//%// Get/Set the given field of a message.
+//%// Get/Set a given field from/to a message.
//%//
//%
//%// Single Fields
@@ -205,53 +416,119 @@ CF_EXTERN_C_END
//%GPB_ACCESSOR_SINGLE(UInt64, uint64_t, n)
//%GPB_ACCESSOR_SINGLE(Float, float, )
//%GPB_ACCESSOR_SINGLE(Double, double, )
-//%/// Get the given enum field of a message. For proto3, if the value isn't a
-//%/// member of the enum, @c kGPBUnrecognizedEnumeratorValue will be returned.
-//%/// GPBGetMessageRawEnumField will bypass the check and return whatever value
-//%/// was set.
+//%/**
+//% * Gets the given enum field of a message. For proto3, if the value isn't a
+//% * member of the enum, @c kGPBUnrecognizedEnumeratorValue will be returned.
+//% * GPBGetMessageRawEnumField will bypass the check and return whatever value
+//% * was set.
+//% *
+//% * @param self The message from which to get the field.
+//% * @param field The field to get.
+//% *
+//% * @return The enum value for the given field.
+//% **/
//%int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field);
-//%/// Set the given enum field of a message. You can only set values that are
-//%/// members of the enum.
-//%void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value);
-//%/// Get the given enum field of a message. No check is done to ensure the value
-//%/// was defined in the enum.
+//%
+//%/**
+//% * Set the given enum field of a message. You can only set values that are
+//% * members of the enum.
+//% *
+//% * @param self The message into which to set the field.
+//% * @param field The field to set.
+//% * @param value The enum value to set in the field.
+//% **/
+//%void GPBSetMessageEnumField(GPBMessage *self,
+//% GPBFieldDescriptor *field,
+//% int32_t value);
+//%
+//%/**
+//% * Get the given enum field of a message. No check is done to ensure the value
+//% * was defined in the enum.
+//% *
+//% * @param self The message from which to get the field.
+//% * @param field The field to get.
+//% *
+//% * @return The raw enum value for the given field.
+//% **/
//%int32_t GPBGetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field);
-//%/// Set the given enum field of a message. You can set the value to anything,
-//%/// even a value that is not a member of the enum.
-//%void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value);
+//%
+//%/**
+//% * Set the given enum field of a message. You can set the value to anything,
+//% * even a value that is not a member of the enum.
+//% *
+//% * @param self The message into which to set the field.
+//% * @param field The field to set.
+//% * @param value The raw enum value to set in the field.
+//% **/
+//%void GPBSetMessageRawEnumField(GPBMessage *self,
+//% GPBFieldDescriptor *field,
+//% int32_t value);
//%
//%// Repeated Fields
//%
-//%/// Gets the value of a repeated field.
-//%///
-//%/// The result will be @c GPB*Array or @c NSMutableArray based on the
-//%/// field's type.
+//%/**
+//% * Gets the value of a repeated field.
+//% *
+//% * @param self The message from which to get the field.
+//% * @param field The repeated field to get.
+//% *
+//% * @return A GPB*Array or an NSMutableArray based on the field's type.
+//% **/
//%id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field);
-//%/// Sets the value of a repeated field.
-//%///
-//%/// The value should be @c GPB*Array or @c NSMutableArray based on the
-//%/// field's type.
-//%void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array);
+//%
+//%/**
+//% * Sets the value of a repeated field.
+//% *
+//% * @param self The message into which to set the field.
+//% * @param field The field to set.
+//% * @param array A GPB*Array or NSMutableArray based on the field's type.
+//% **/
+//%void GPBSetMessageRepeatedField(GPBMessage *self,
+//% GPBFieldDescriptor *field,
+//% id array);
//%
//%// Map Fields
//%
-//%/// Gets the value of a map<> field.
-//%///
-//%/// The result will be @c GPB*Dictionary or @c NSMutableDictionary based on
-//%/// the field's type.
+//%/**
+//% * Gets the value of a map<> field.
+//% *
+//% * @param self The message from which to get the field.
+//% * @param field The repeated field to get.
+//% *
+//% * @return A GPB*Dictionary or NSMutableDictionary based on the field's type.
+//% **/
//%id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field);
-//%/// Sets the value of a map<> field.
-//%///
-//%/// The object should be @c GPB*Dictionary or @c NSMutableDictionary based
-//%/// on the field's type.
-//%void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, id dictionary);
+//%
+//%/**
+//% * Sets the value of a map<> field.
+//% *
+//% * @param self The message into which to set the field.
+//% * @param field The field to set.
+//% * @param dictionary A GPB*Dictionary or NSMutableDictionary based on the
+//% * field's type.
+//% **/
+//%void GPBSetMessageMapField(GPBMessage *self,
+//% GPBFieldDescriptor *field,
+//% id dictionary);
//%
//%PDDM-DEFINE GPB_ACCESSOR_SINGLE(NAME, TYPE, AN)
//%GPB_ACCESSOR_SINGLE_FULL(NAME, TYPE, AN, )
//%PDDM-DEFINE GPB_ACCESSOR_SINGLE_FULL(NAME, TYPE, AN, TisP)
-//%/// Gets the value of a##AN NAME$L field.
+//%/**
+//% * Gets the value of a##AN NAME$L field.
+//% *
+//% * @param self The message from which to get the field.
+//% * @param field The field to get.
+//% **/
//%TYPE TisP##GPBGetMessage##NAME##Field(GPBMessage *self, GPBFieldDescriptor *field);
-//%/// Sets the value of a##AN NAME$L field.
+//%
+//%/**
+//% * Sets the value of a##AN NAME$L field.
+//% *
+//% * @param self The message into which to set the field.
+//% * @param field The field to set.
+//% * @param value The to set in the field.
+//% **/
//%void GPBSetMessage##NAME##Field(GPBMessage *self, GPBFieldDescriptor *field, TYPE TisP##value);
//%
diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m
index 05375084..80b85d07 100644
--- a/objectivec/GPBUtilities.m
+++ b/objectivec/GPBUtilities.m
@@ -218,9 +218,10 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
//% TYPE *typePtr = (TYPE *)&storage[field->description_->offset];
//% *typePtr = value;
//% // proto2: any value counts as having been set; proto3, it
-//% // has to be a non zero value.
-//% BOOL hasValue =
-//% (syntax == GPBFileSyntaxProto2) || (value != (TYPE)0);
+//% // has to be a non zero value or be in a oneof.
+//% BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
+//% || (value != (TYPE)0)
+//% || (field->containingOneof_ != NULL));
//% GPBSetHasIvarField(self, field, hasValue);
//% GPBBecomeVisibleToAutocreator(self);
//%}
@@ -337,8 +338,19 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self,
// zero, they are being cleared.
if ((syntax == GPBFileSyntaxProto3) && !fieldIsMessage &&
([value length] == 0)) {
- setHasValue = NO;
- value = nil;
+ // Except, if the field was in a oneof, then it still gets recorded as
+ // having been set so the state of the oneof can be serialized back out.
+ if (!oneof) {
+ setHasValue = NO;
+ }
+ if (setHasValue) {
+ NSCAssert(value != nil, @"Should never be setting has for nil");
+ } else {
+ // The value passed in was retained, it must be released since we
+ // aren't saving anything in the field.
+ [value release];
+ value = nil;
+ }
}
GPBSetHasIvarField(self, field, setHasValue);
}
@@ -524,9 +536,10 @@ void GPBSetBoolIvarWithFieldInternal(GPBMessage *self,
GPBSetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number, value);
// proto2: any value counts as having been set; proto3, it
- // has to be a non zero value.
- BOOL hasValue =
- (syntax == GPBFileSyntaxProto2) || (value != (BOOL)0);
+ // has to be a non zero value or be in a oneof.
+ BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
+ || (value != (BOOL)0)
+ || (field->containingOneof_ != NULL));
GPBSetHasIvarField(self, field, hasValue);
GPBBecomeVisibleToAutocreator(self);
}
@@ -573,9 +586,10 @@ void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
int32_t *typePtr = (int32_t *)&storage[field->description_->offset];
*typePtr = value;
// proto2: any value counts as having been set; proto3, it
- // has to be a non zero value.
- BOOL hasValue =
- (syntax == GPBFileSyntaxProto2) || (value != (int32_t)0);
+ // has to be a non zero value or be in a oneof.
+ BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
+ || (value != (int32_t)0)
+ || (field->containingOneof_ != NULL));
GPBSetHasIvarField(self, field, hasValue);
GPBBecomeVisibleToAutocreator(self);
}
@@ -622,9 +636,10 @@ void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self,
uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset];
*typePtr = value;
// proto2: any value counts as having been set; proto3, it
- // has to be a non zero value.
- BOOL hasValue =
- (syntax == GPBFileSyntaxProto2) || (value != (uint32_t)0);
+ // has to be a non zero value or be in a oneof.
+ BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
+ || (value != (uint32_t)0)
+ || (field->containingOneof_ != NULL));
GPBSetHasIvarField(self, field, hasValue);
GPBBecomeVisibleToAutocreator(self);
}
@@ -671,9 +686,10 @@ void GPBSetInt64IvarWithFieldInternal(GPBMessage *self,
int64_t *typePtr = (int64_t *)&storage[field->description_->offset];
*typePtr = value;
// proto2: any value counts as having been set; proto3, it
- // has to be a non zero value.
- BOOL hasValue =
- (syntax == GPBFileSyntaxProto2) || (value != (int64_t)0);
+ // has to be a non zero value or be in a oneof.
+ BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
+ || (value != (int64_t)0)
+ || (field->containingOneof_ != NULL));
GPBSetHasIvarField(self, field, hasValue);
GPBBecomeVisibleToAutocreator(self);
}
@@ -720,9 +736,10 @@ void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self,
uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset];
*typePtr = value;
// proto2: any value counts as having been set; proto3, it
- // has to be a non zero value.
- BOOL hasValue =
- (syntax == GPBFileSyntaxProto2) || (value != (uint64_t)0);
+ // has to be a non zero value or be in a oneof.
+ BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
+ || (value != (uint64_t)0)
+ || (field->containingOneof_ != NULL));
GPBSetHasIvarField(self, field, hasValue);
GPBBecomeVisibleToAutocreator(self);
}
@@ -769,9 +786,10 @@ void GPBSetFloatIvarWithFieldInternal(GPBMessage *self,
float *typePtr = (float *)&storage[field->description_->offset];
*typePtr = value;
// proto2: any value counts as having been set; proto3, it
- // has to be a non zero value.
- BOOL hasValue =
- (syntax == GPBFileSyntaxProto2) || (value != (float)0);
+ // has to be a non zero value or be in a oneof.
+ BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
+ || (value != (float)0)
+ || (field->containingOneof_ != NULL));
GPBSetHasIvarField(self, field, hasValue);
GPBBecomeVisibleToAutocreator(self);
}
@@ -818,9 +836,10 @@ void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self,
double *typePtr = (double *)&storage[field->description_->offset];
*typePtr = value;
// proto2: any value counts as having been set; proto3, it
- // has to be a non zero value.
- BOOL hasValue =
- (syntax == GPBFileSyntaxProto2) || (value != (double)0);
+ // has to be a non zero value or be in a oneof.
+ BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
+ || (value != (double)0)
+ || (field->containingOneof_ != NULL));
GPBSetHasIvarField(self, field, hasValue);
GPBBecomeVisibleToAutocreator(self);
}
@@ -1052,7 +1071,15 @@ static void AppendStringEscaped(NSString *toPrint, NSMutableString *destStr) {
case '\'': [destStr appendString:@"\\\'"]; break;
case '\\': [destStr appendString:@"\\\\"]; break;
default:
- [destStr appendFormat:@"%C", aChar];
+ // This differs slightly from the C++ code in that the C++ doesn't
+ // generate UTF8; it looks at the string in UTF8, but escapes every
+ // byte > 0x7E.
+ if (aChar < 0x20) {
+ [destStr appendFormat:@"\\%d%d%d",
+ (aChar / 64), ((aChar % 64) / 8), (aChar % 8)];
+ } else {
+ [destStr appendFormat:@"%C", aChar];
+ }
break;
}
}
@@ -1472,7 +1499,8 @@ static void AppendTextFormatForMessage(GPBMessage *message,
NSUInteger fieldCount = fieldsArray.count;
const GPBExtensionRange *extensionRanges = descriptor.extensionRanges;
NSUInteger extensionRangesCount = descriptor.extensionRangesCount;
- NSArray *activeExtensions = [message sortedExtensionsInUse];
+ NSArray *activeExtensions = [[message extensionsCurrentlySet]
+ sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) {
if (i == fieldCount) {
AppendTextFormatForMessageExtensionRange(
diff --git a/objectivec/GPBUtilities_PackagePrivate.h b/objectivec/GPBUtilities_PackagePrivate.h
index c02493b2..a41ee2ab 100644
--- a/objectivec/GPBUtilities_PackagePrivate.h
+++ b/objectivec/GPBUtilities_PackagePrivate.h
@@ -96,7 +96,7 @@ GPB_INLINE int64_t GPBLogicalRightShift64(int64_t value, int32_t spaces) {
// negative values must be sign-extended to 64 bits to be varint encoded,
// thus always taking 10 bytes on the wire.)
GPB_INLINE int32_t GPBDecodeZigZag32(uint32_t n) {
- return GPBLogicalRightShift32(n, 1) ^ -(n & 1);
+ return (int32_t)(GPBLogicalRightShift32((int32_t)n, 1) ^ -((int32_t)(n) & 1));
}
// Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers
@@ -104,7 +104,7 @@ GPB_INLINE int32_t GPBDecodeZigZag32(uint32_t n) {
// negative values must be sign-extended to 64 bits to be varint encoded,
// thus always taking 10 bytes on the wire.)
GPB_INLINE int64_t GPBDecodeZigZag64(uint64_t n) {
- return GPBLogicalRightShift64(n, 1) ^ -(n & 1);
+ return (int64_t)(GPBLogicalRightShift64((int64_t)n, 1) ^ -((int64_t)(n) & 1));
}
// Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers
@@ -113,7 +113,7 @@ GPB_INLINE int64_t GPBDecodeZigZag64(uint64_t n) {
// thus always taking 10 bytes on the wire.)
GPB_INLINE uint32_t GPBEncodeZigZag32(int32_t n) {
// Note: the right-shift must be arithmetic
- return (n << 1) ^ (n >> 31);
+ return (uint32_t)((n << 1) ^ (n >> 31));
}
// Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers
@@ -122,7 +122,7 @@ GPB_INLINE uint32_t GPBEncodeZigZag32(int32_t n) {
// thus always taking 10 bytes on the wire.)
GPB_INLINE uint64_t GPBEncodeZigZag64(int64_t n) {
// Note: the right-shift must be arithmetic
- return (n << 1) ^ (n >> 63);
+ return (uint64_t)((n << 1) ^ (n >> 63));
}
#pragma clang diagnostic push
diff --git a/objectivec/GPBWellKnownTypes.h b/objectivec/GPBWellKnownTypes.h
index 311ac58e..90d96c6f 100644
--- a/objectivec/GPBWellKnownTypes.h
+++ b/objectivec/GPBWellKnownTypes.h
@@ -37,27 +37,198 @@
#endif
#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS
+ #import <Protobuf/Any.pbobjc.h>
#import <Protobuf/Duration.pbobjc.h>
#import <Protobuf/Timestamp.pbobjc.h>
#else
+ #import "google/protobuf/Any.pbobjc.h"
#import "google/protobuf/Duration.pbobjc.h"
#import "google/protobuf/Timestamp.pbobjc.h"
#endif
NS_ASSUME_NONNULL_BEGIN
-// Extension to GPBTimestamp to work with standard Foundation time/date types.
+#pragma mark - Errors
+
+/** NSError domain used for errors. */
+extern NSString *const GPBWellKnownTypesErrorDomain;
+
+/** Error code for NSError with GPBWellKnownTypesErrorDomain. */
+typedef NS_ENUM(NSInteger, GPBWellKnownTypesErrorCode) {
+ /** The type_url could not be computed for the requested GPBMessage class. */
+ GPBWellKnownTypesErrorCodeFailedToComputeTypeURL = -100,
+ /** type_url in a Any doesn’t match that of the requested GPBMessage class. */
+ GPBWellKnownTypesErrorCodeTypeURLMismatch = -101,
+};
+
+#pragma mark - GPBTimestamp
+
+/**
+ * Category for GPBTimestamp to work with standard Foundation time/date types.
+ **/
@interface GPBTimestamp (GBPWellKnownTypes)
+
+/** The NSDate representation of this GPBTimestamp. */
@property(nonatomic, readwrite, strong) NSDate *date;
+
+/**
+ * The NSTimeInterval representation of this GPBTimestamp.
+ *
+ * @note: Not all second/nanos combinations can be represented in a
+ * NSTimeInterval, so getting this could be a lossy transform.
+ **/
@property(nonatomic, readwrite) NSTimeInterval timeIntervalSince1970;
+
+/**
+ * Initializes a GPBTimestamp with the given NSDate.
+ *
+ * @param date The date to configure the GPBTimestamp with.
+ *
+ * @return A newly initialized GPBTimestamp.
+ **/
- (instancetype)initWithDate:(NSDate *)date;
+
+/**
+ * Initializes a GPBTimestamp with the given NSTimeInterval.
+ *
+ * @param timeIntervalSince1970 Time interval to configure the GPBTimestamp with.
+ *
+ * @return A newly initialized GPBTimestamp.
+ **/
- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970;
+
@end
-// Extension to GPBDuration to work with standard Foundation time type.
+#pragma mark - GPBDuration
+
+/**
+ * Category for GPBDuration to work with standard Foundation time type.
+ **/
@interface GPBDuration (GBPWellKnownTypes)
+
+/**
+ * The NSTimeInterval representation of this GPBDuration.
+ *
+ * @note: Not all second/nanos combinations can be represented in a
+ * NSTimeInterval, so getting this could be a lossy transform.
+ **/
@property(nonatomic, readwrite) NSTimeInterval timeIntervalSince1970;
+
+/**
+ * Initializes a GPBDuration with the given NSTimeInterval.
+ *
+ * @param timeIntervalSince1970 Time interval to configure the GPBDuration with.
+ *
+ * @return A newly initialized GPBDuration.
+ **/
- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970;
+
+@end
+
+#pragma mark - GPBAny
+
+/**
+ * Category for GPBAny to help work with the message within the object.
+ **/
+@interface GPBAny (GBPWellKnownTypes)
+
+/**
+ * Convenience method to create a GPBAny containing the serialized message.
+ * This uses type.googleapis.com/ as the type_url's prefix.
+ *
+ * @param message The message to be packed into the GPBAny.
+ * @param errorPtr Pointer to an error that will be populated if something goes
+ * wrong.
+ *
+ * @return A newly configured GPBAny with the given message, or nil on failure.
+ */
++ (nullable instancetype)anyWithMessage:(nonnull GPBMessage *)message
+ error:(NSError **)errorPtr;
+
+/**
+ * Convenience method to create a GPBAny containing the serialized message.
+ *
+ * @param message The message to be packed into the GPBAny.
+ * @param typeURLPrefix The URL prefix to apply for type_url.
+ * @param errorPtr Pointer to an error that will be populated if something
+ * goes wrong.
+ *
+ * @return A newly configured GPBAny with the given message, or nil on failure.
+ */
++ (nullable instancetype)anyWithMessage:(nonnull GPBMessage *)message
+ typeURLPrefix:(nonnull NSString *)typeURLPrefix
+ error:(NSError **)errorPtr;
+
+/**
+ * Initializes a GPBAny to contain the serialized message. This uses
+ * type.googleapis.com/ as the type_url's prefix.
+ *
+ * @param message The message to be packed into the GPBAny.
+ * @param errorPtr Pointer to an error that will be populated if something goes
+ * wrong.
+ *
+ * @return A newly configured GPBAny with the given message, or nil on failure.
+ */
+- (nullable instancetype)initWithMessage:(nonnull GPBMessage *)message
+ error:(NSError **)errorPtr;
+
+/**
+ * Initializes a GPBAny to contain the serialized message.
+ *
+ * @param message The message to be packed into the GPBAny.
+ * @param typeURLPrefix The URL prefix to apply for type_url.
+ * @param errorPtr Pointer to an error that will be populated if something
+ * goes wrong.
+ *
+ * @return A newly configured GPBAny with the given message, or nil on failure.
+ */
+- (nullable instancetype)initWithMessage:(nonnull GPBMessage *)message
+ typeURLPrefix:(nonnull NSString *)typeURLPrefix
+ error:(NSError **)errorPtr;
+
+/**
+ * Packs the serialized message into this GPBAny. This uses
+ * type.googleapis.com/ as the type_url's prefix.
+ *
+ * @param message The message to be packed into the GPBAny.
+ * @param errorPtr Pointer to an error that will be populated if something goes
+ * wrong.
+ *
+ * @return Whether the packing was successful or not.
+ */
+- (BOOL)packWithMessage:(nonnull GPBMessage *)message
+ error:(NSError **)errorPtr;
+
+/**
+ * Packs the serialized message into this GPBAny.
+ *
+ * @param message The message to be packed into the GPBAny.
+ * @param typeURLPrefix The URL prefix to apply for type_url.
+ * @param errorPtr Pointer to an error that will be populated if something
+ * goes wrong.
+ *
+ * @return Whether the packing was successful or not.
+ */
+- (BOOL)packWithMessage:(nonnull GPBMessage *)message
+ typeURLPrefix:(nonnull NSString *)typeURLPrefix
+ error:(NSError **)errorPtr;
+
+/**
+ * Unpacks the serialized message as if it was an instance of the given class.
+ *
+ * @note When checking type_url, the base URL is not checked, only the fully
+ * qualified name.
+ *
+ * @param messageClass The class to use to deserialize the contained message.
+ * @param errorPtr Pointer to an error that will be populated if something
+ * goes wrong.
+ *
+ * @return An instance of the given class populated with the contained data, or
+ * nil on failure.
+ */
+- (nullable GPBMessage *)unpackMessageClass:(Class)messageClass
+ error:(NSError **)errorPtr;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/objectivec/GPBWellKnownTypes.m b/objectivec/GPBWellKnownTypes.m
index 5cdd62d5..ed798a2e 100644
--- a/objectivec/GPBWellKnownTypes.m
+++ b/objectivec/GPBWellKnownTypes.m
@@ -34,6 +34,13 @@
#import "GPBWellKnownTypes.h"
+#import "GPBUtilities_PackagePrivate.h"
+
+NSString *const GPBWellKnownTypesErrorDomain =
+ GPBNSStringifySymbol(GPBWellKnownTypesErrorDomain);
+
+static NSString *kTypePrefixGoogleApisCom = @"type.googleapis.com/";
+
static NSTimeInterval TimeIntervalSince1970FromSecondsAndNanos(int64_t seconds,
int32_t nanos) {
return seconds + (NSTimeInterval)nanos / 1e9;
@@ -48,6 +55,30 @@ static int32_t SecondsAndNanosFromTimeIntervalSince1970(NSTimeInterval time,
return (int32_t)nanos;
}
+static NSString *BuildTypeURL(NSString *typeURLPrefix, NSString *fullName) {
+ if (typeURLPrefix.length == 0) {
+ return fullName;
+ }
+
+ if ([typeURLPrefix hasSuffix:@"/"]) {
+ return [typeURLPrefix stringByAppendingString:fullName];
+ }
+
+ return [NSString stringWithFormat:@"%@/%@", typeURLPrefix, fullName];
+}
+
+static NSString *ParseTypeFromURL(NSString *typeURLString) {
+ NSRange range = [typeURLString rangeOfString:@"/" options:NSBackwardsSearch];
+ if ((range.location == NSNotFound) ||
+ (NSMaxRange(range) == typeURLString.length)) {
+ return nil;
+ }
+ NSString *result = [typeURLString substringFromIndex:range.location + 1];
+ return result;
+}
+
+#pragma mark - GPBTimestamp
+
@implementation GPBTimestamp (GBPWellKnownTypes)
- (instancetype)initWithDate:(NSDate *)date {
@@ -87,6 +118,8 @@ static int32_t SecondsAndNanosFromTimeIntervalSince1970(NSTimeInterval time,
@end
+#pragma mark - GPBDuration
+
@implementation GPBDuration (GBPWellKnownTypes)
- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 {
@@ -113,3 +146,105 @@ static int32_t SecondsAndNanosFromTimeIntervalSince1970(NSTimeInterval time,
}
@end
+
+#pragma mark - GPBAny
+
+@implementation GPBAny (GBPWellKnownTypes)
+
++ (instancetype)anyWithMessage:(GPBMessage *)message
+ error:(NSError **)errorPtr {
+ return [self anyWithMessage:message
+ typeURLPrefix:kTypePrefixGoogleApisCom
+ error:errorPtr];
+}
+
++ (instancetype)anyWithMessage:(GPBMessage *)message
+ typeURLPrefix:(NSString *)typeURLPrefix
+ error:(NSError **)errorPtr {
+ return [[[self alloc] initWithMessage:message
+ typeURLPrefix:typeURLPrefix
+ error:errorPtr] autorelease];
+}
+
+- (instancetype)initWithMessage:(GPBMessage *)message
+ error:(NSError **)errorPtr {
+ return [self initWithMessage:message
+ typeURLPrefix:kTypePrefixGoogleApisCom
+ error:errorPtr];
+}
+
+- (instancetype)initWithMessage:(GPBMessage *)message
+ typeURLPrefix:(NSString *)typeURLPrefix
+ error:(NSError **)errorPtr {
+ self = [self init];
+ if (self) {
+ if (![self packWithMessage:message
+ typeURLPrefix:typeURLPrefix
+ error:errorPtr]) {
+ [self release];
+ self = nil;
+ }
+ }
+ return self;
+}
+
+- (BOOL)packWithMessage:(GPBMessage *)message
+ error:(NSError **)errorPtr {
+ return [self packWithMessage:message
+ typeURLPrefix:kTypePrefixGoogleApisCom
+ error:errorPtr];
+}
+
+- (BOOL)packWithMessage:(GPBMessage *)message
+ typeURLPrefix:(NSString *)typeURLPrefix
+ error:(NSError **)errorPtr {
+ NSString *fullName = [message descriptor].fullName;
+ if (fullName.length == 0) {
+ if (errorPtr) {
+ *errorPtr =
+ [NSError errorWithDomain:GPBWellKnownTypesErrorDomain
+ code:GPBWellKnownTypesErrorCodeFailedToComputeTypeURL
+ userInfo:nil];
+ }
+ return NO;
+ }
+ if (errorPtr) {
+ *errorPtr = nil;
+ }
+ self.typeURL = BuildTypeURL(typeURLPrefix, fullName);
+ self.value = message.data;
+ return YES;
+}
+
+- (GPBMessage *)unpackMessageClass:(Class)messageClass
+ error:(NSError **)errorPtr {
+ NSString *fullName = [messageClass descriptor].fullName;
+ if (fullName.length == 0) {
+ if (errorPtr) {
+ *errorPtr =
+ [NSError errorWithDomain:GPBWellKnownTypesErrorDomain
+ code:GPBWellKnownTypesErrorCodeFailedToComputeTypeURL
+ userInfo:nil];
+ }
+ return nil;
+ }
+
+ NSString *expectedFullName = ParseTypeFromURL(self.typeURL);
+ if ((expectedFullName == nil) || ![expectedFullName isEqual:fullName]) {
+ if (errorPtr) {
+ *errorPtr =
+ [NSError errorWithDomain:GPBWellKnownTypesErrorDomain
+ code:GPBWellKnownTypesErrorCodeTypeURLMismatch
+ userInfo:nil];
+ }
+ return nil;
+ }
+
+ // Any is proto3, which means no extensions, so this assumes anything put
+ // within an any also won't need extensions. A second helper could be added
+ // if needed.
+ return [messageClass parseFromData:self.value
+ error:errorPtr];
+}
+
+@end
diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
index 32067910..1585dbed 100644
--- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
@@ -65,6 +65,7 @@
F4E675A11B21D0000054530B /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675911B21D0000054530B /* Struct.pbobjc.m */; };
F4E675A31B21D0000054530B /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675931B21D0000054530B /* Type.pbobjc.m */; };
F4E675A51B21D0000054530B /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675951B21D0000054530B /* Wrappers.pbobjc.m */; };
+ F4F8D8831D789FD9002CE128 /* GPBUnittestProtos2.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F8D8811D789FCE002CE128 /* GPBUnittestProtos2.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -211,6 +212,7 @@
F4E675AB1B21D05C0054530B /* struct.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = struct.proto; path = ../src/google/protobuf/struct.proto; sourceTree = "<group>"; };
F4E675AC1B21D05C0054530B /* type.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = type.proto; path = ../src/google/protobuf/type.proto; sourceTree = "<group>"; };
F4E675AD1B21D05C0054530B /* wrappers.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = wrappers.proto; path = ../src/google/protobuf/wrappers.proto; sourceTree = "<group>"; };
+ F4F8D8811D789FCE002CE128 /* GPBUnittestProtos2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos2.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -408,6 +410,7 @@
7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */,
7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */,
8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */,
+ F4F8D8811D789FCE002CE128 /* GPBUnittestProtos2.m */,
7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */,
7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */,
8B4248DB1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m */,
@@ -659,6 +662,7 @@
F4B51B1E1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */,
F4487C7F1AAF62CD00531423 /* GPBMessageTests+Serialization.m in Sources */,
8B4248DC1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m in Sources */,
+ F4F8D8831D789FD9002CE128 /* GPBUnittestProtos2.m in Sources */,
F4353D1D1AB8822D005A6198 /* GPBDescriptorTests.m in Sources */,
8B4248BB1A8C256A00BC1EC6 /* GPBSwiftTests.swift in Sources */,
5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */,
@@ -778,6 +782,7 @@
CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
CLANG_STATIC_ANALYZER_MODE = deep;
+ CLANG_WARN_ASSIGN_ENUM = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES;
@@ -838,6 +843,7 @@
CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
CLANG_STATIC_ANALYZER_MODE = deep;
+ CLANG_WARN_ASSIGN_ENUM = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES;
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
index 9f688f8d..b6bc95ab 100644
--- a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
@@ -73,6 +73,7 @@
F4E675D51B21D1620054530B /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C21B21D1440054530B /* Struct.pbobjc.m */; };
F4E675D61B21D1620054530B /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C51B21D1440054530B /* Type.pbobjc.m */; };
F4E675D71B21D1620054530B /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C71B21D1440054530B /* Wrappers.pbobjc.m */; };
+ F4F8D8861D78A193002CE128 /* GPBUnittestProtos2.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F8D8841D78A186002CE128 /* GPBUnittestProtos2.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -234,6 +235,7 @@
F4E675DD1B21D1DE0054530B /* struct.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = struct.proto; path = ../src/google/protobuf/struct.proto; sourceTree = "<group>"; };
F4E675DE1B21D1DE0054530B /* type.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = type.proto; path = ../src/google/protobuf/type.proto; sourceTree = "<group>"; };
F4E675DF1B21D1DE0054530B /* wrappers.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = wrappers.proto; path = ../src/google/protobuf/wrappers.proto; sourceTree = "<group>"; };
+ F4F8D8841D78A186002CE128 /* GPBUnittestProtos2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos2.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -446,6 +448,7 @@
7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */,
7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */,
8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */,
+ F4F8D8841D78A186002CE128 /* GPBUnittestProtos2.m */,
7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */,
7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */,
8B4248E51A929C9900BC1EC6 /* GPBWellKnownTypesTest.m */,
@@ -755,6 +758,7 @@
F4487C811AAF62FC00531423 /* GPBMessageTests+Serialization.m in Sources */,
8B4248E61A929C9900BC1EC6 /* GPBWellKnownTypesTest.m in Sources */,
F4353D1F1AB88243005A6198 /* GPBDescriptorTests.m in Sources */,
+ F4F8D8861D78A193002CE128 /* GPBUnittestProtos2.m in Sources */,
F4B51B1C1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */,
8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */,
5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */,
@@ -940,6 +944,7 @@
CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
CLANG_STATIC_ANALYZER_MODE = deep;
+ CLANG_WARN_ASSIGN_ENUM = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES;
@@ -1001,6 +1006,7 @@
CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
CLANG_STATIC_ANALYZER_MODE = deep;
+ CLANG_WARN_ASSIGN_ENUM = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES;
diff --git a/objectivec/Tests/GPBCodedOuputStreamTests.m b/objectivec/Tests/GPBCodedOuputStreamTests.m
index 0723b645..2ad326be 100644
--- a/objectivec/Tests/GPBCodedOuputStreamTests.m
+++ b/objectivec/Tests/GPBCodedOuputStreamTests.m
@@ -193,6 +193,32 @@
}
}
+- (void)assertWriteStringNoTag:(NSData*)data
+ value:(NSString *)value
+ context:(NSString *)contextMessage {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+ [output writeStringNoTag:value];
+ [output flush];
+
+ NSData* actual =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual, @"%@", contextMessage);
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ rawOutput = [NSOutputStream outputStreamToMemory];
+ output = [GPBCodedOutputStream streamWithOutputStream:rawOutput
+ bufferSize:blockSize];
+ [output writeStringNoTag:value];
+ [output flush];
+
+ actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual, @"%@", contextMessage);
+ }
+}
+
- (void)testWriteVarint1 {
[self assertWriteVarint:bytes(0x00) value:0];
}
@@ -337,4 +363,64 @@
XCTAssertEqualObjects(rawBytes, goldenData);
}
+- (void)testCFStringGetCStringPtrAndStringsWithNullChars {
+ // This test exists to verify that CFStrings with embedded NULLs still expose
+ // their raw buffer if they are backed by UTF8 storage. If this fails, the
+ // quick/direct access paths in GPBCodedOutputStream that depend on
+ // CFStringGetCStringPtr need to be re-evalutated (maybe just removed).
+ // And yes, we do get NULLs in strings from some servers.
+
+ char zeroTest[] = "\0Test\0String";
+ // Note: there is a \0 at the end of this since it is a c-string.
+ NSString *asNSString = [[NSString alloc] initWithBytes:zeroTest
+ length:sizeof(zeroTest)
+ encoding:NSUTF8StringEncoding];
+ const char *cString =
+ CFStringGetCStringPtr((CFStringRef)asNSString, kCFStringEncodingUTF8);
+ XCTAssertTrue(cString != NULL);
+ // Again, if the above assert fails, then it means NSString no longer exposes
+ // the raw utf8 storage of a string created from utf8 input, so the code using
+ // CFStringGetCStringPtr in GPBCodedOutputStream will still work (it will take
+ // a different code path); but the optimizations for when
+ // CFStringGetCStringPtr does work could possibly go away.
+
+ XCTAssertEqual(sizeof(zeroTest),
+ [asNSString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
+ XCTAssertTrue(0 == memcmp(cString, zeroTest, sizeof(zeroTest)));
+ [asNSString release];
+}
+
+- (void)testWriteStringsWithZeroChar {
+ // Unicode allows `\0` as a character, and NSString is a class cluster, so
+ // there are a few different classes that could end up beind a given string.
+ // Historically, we've seen differences based on constant strings in code and
+ // strings built via the NSString apis. So this round trips them to ensure
+ // they are acting as expected.
+
+ NSArray<NSString *> *strs = @[
+ @"\0at start",
+ @"in\0middle",
+ @"at end\0",
+ ];
+ int i = 0;
+ for (NSString *str in strs) {
+ NSData *asUTF8 = [str dataUsingEncoding:NSUTF8StringEncoding];
+ NSMutableData *expected = [NSMutableData data];
+ uint8_t lengthByte = (uint8_t)asUTF8.length;
+ [expected appendBytes:&lengthByte length:1];
+ [expected appendData:asUTF8];
+
+ NSString *context = [NSString stringWithFormat:@"Loop %d - Literal", i];
+ [self assertWriteStringNoTag:expected value:str context:context];
+
+ // Force a new string to be built which gets a different class from the
+ // NSString class cluster than the literal did.
+ NSString *str2 = [NSString stringWithFormat:@"%@", str];
+ context = [NSString stringWithFormat:@"Loop %d - Built", i];
+ [self assertWriteStringNoTag:expected value:str2 context:context];
+
+ ++i;
+ }
+}
+
@end
diff --git a/objectivec/Tests/GPBDescriptorTests.m b/objectivec/Tests/GPBDescriptorTests.m
index 74e3172b..1e1c3de8 100644
--- a/objectivec/Tests/GPBDescriptorTests.m
+++ b/objectivec/Tests/GPBDescriptorTests.m
@@ -34,12 +34,41 @@
#import "GPBDescriptor.h"
#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestObjc.pbobjc.h"
+#import "google/protobuf/Descriptor.pbobjc.h"
@interface DescriptorTests : GPBTestCase
@end
@implementation DescriptorTests
+- (void)testDescriptor_containingType {
+ GPBDescriptor *testAllTypesDesc = [TestAllTypes descriptor];
+ GPBDescriptor *nestedMessageDesc = [TestAllTypes_NestedMessage descriptor];
+ XCTAssertNil(testAllTypesDesc.containingType);
+ XCTAssertNotNil(nestedMessageDesc.containingType);
+ XCTAssertEqual(nestedMessageDesc.containingType, testAllTypesDesc); // Ptr comparison
+}
+
+- (void)testDescriptor_fullName {
+ GPBDescriptor *testAllTypesDesc = [TestAllTypes descriptor];
+ XCTAssertEqualObjects(testAllTypesDesc.fullName, @"protobuf_unittest.TestAllTypes");
+ GPBDescriptor *nestedMessageDesc = [TestAllTypes_NestedMessage descriptor];
+ XCTAssertEqualObjects(nestedMessageDesc.fullName, @"protobuf_unittest.TestAllTypes.NestedMessage");
+
+ // Prefixes removed.
+ GPBDescriptor *descDesc = [GPBDescriptorProto descriptor];
+ XCTAssertEqualObjects(descDesc.fullName, @"google.protobuf.DescriptorProto");
+ GPBDescriptor *descExtRngDesc = [GPBDescriptorProto_ExtensionRange descriptor];
+ XCTAssertEqualObjects(descExtRngDesc.fullName, @"google.protobuf.DescriptorProto.ExtensionRange");
+
+ // Things that get "_Class" added.
+ GPBDescriptor *pointDesc = [Point_Class descriptor];
+ XCTAssertEqualObjects(pointDesc.fullName, @"protobuf_unittest.Point");
+ GPBDescriptor *pointRectDesc = [Point_Rect descriptor];
+ XCTAssertEqualObjects(pointRectDesc.fullName, @"protobuf_unittest.Point.Rect");
+}
+
- (void)testFieldDescriptor {
GPBDescriptor *descriptor = [TestAllTypes descriptor];
diff --git a/objectivec/Tests/GPBMessageTests+Runtime.m b/objectivec/Tests/GPBMessageTests+Runtime.m
index 1520381b..0058311b 100644
--- a/objectivec/Tests/GPBMessageTests+Runtime.m
+++ b/objectivec/Tests/GPBMessageTests+Runtime.m
@@ -36,6 +36,7 @@
#import "google/protobuf/MapUnittest.pbobjc.h"
#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestCycle.pbobjc.h"
#import "google/protobuf/UnittestObjcStartup.pbobjc.h"
#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
@@ -49,11 +50,24 @@
// specific.
- (void)testStartupOrdering {
- // Just have to create a message. Nothing else uses the classes from
- // this file, so the first selector invoked on the class will initialize
- // it, which also initializes the root.
+ // Message class/Root class initialization is a little tricky, so these just
+ // create some possible patterns that can be a problem. The messages don't
+ // have to be exercised, just creating them is enough to test. If there
+ // is a problem, the runtime should assert or hang.
+ //
+ // Note: the messages from these proto files should not be used in any other
+ // tests, that way when they are referenced here it will be the first use and
+ // initialization will take place now.
+
TestObjCStartupMessage *message = [TestObjCStartupMessage message];
XCTAssertNotNil(message);
+
+ CycleBaz *baz = [CycleBaz message];
+ CycleBar *bar = [CycleBar message];
+ CycleFoo *foo = [CycleFoo message];
+ XCTAssertNotNil(baz);
+ XCTAssertNotNil(bar);
+ XCTAssertNotNil(foo);
}
- (void)testProto2HasMethodSupport {
@@ -326,6 +340,17 @@
//% [msg release];
//% }
//%
+//%PDDM-DEFINE PROTO2_TEST_CLEAR_FIELD_WITH_NIL(FIELD, VALUE)
+//% { // optional##FIELD
+//% Message2 *msg = [[Message2 alloc] init];
+//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_Optional##FIELD));
+//% msg.optional##FIELD = VALUE;
+//% XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_Optional##FIELD));
+//% msg.optional##FIELD = nil;
+//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_Optional##FIELD));
+//% [msg release];
+//% }
+//%
//%PDDM-DEFINE PROTO2_TEST_HAS_FIELDS()
//%PROTO2_TEST_HAS_FIELD(Int32, 1, 0)
//%PROTO2_TEST_HAS_FIELD(Int64, 1, 0)
@@ -347,6 +372,14 @@
//% //
//%
//%PROTO2_TEST_HAS_FIELD(Enum, Message2_Enum_Bar, Message2_Enum_Foo)
+//% //
+//% // Nil can also be used to clear strings, bytes, groups, and messages.
+//% //
+//%
+//%PROTO2_TEST_CLEAR_FIELD_WITH_NIL(String, @"foo")
+//%PROTO2_TEST_CLEAR_FIELD_WITH_NIL(Bytes, [@"foo" dataUsingEncoding:NSUTF8StringEncoding])
+//%PROTO2_TEST_CLEAR_FIELD_WITH_NIL(Group, [Message2_OptionalGroup message])
+//%PROTO2_TEST_CLEAR_FIELD_WITH_NIL(Message, [Message2 message])
//%PDDM-EXPAND PROTO2_TEST_HAS_FIELDS()
// This block of code is generated, do not edit it directly.
@@ -658,13 +691,57 @@
[msg release];
}
+ //
+ // Nil can also be used to clear strings, bytes, groups, and messages.
+ //
+
+ { // optionalString
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalString));
+ msg.optionalString = @"foo";
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalString));
+ msg.optionalString = nil;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalString));
+ [msg release];
+ }
+
+ { // optionalBytes
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBytes));
+ msg.optionalBytes = [@"foo" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBytes));
+ msg.optionalBytes = nil;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBytes));
+ [msg release];
+ }
+
+ { // optionalGroup
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalGroup));
+ msg.optionalGroup = [Message2_OptionalGroup message];
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalGroup));
+ msg.optionalGroup = nil;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalGroup));
+ [msg release];
+ }
+
+ { // optionalMessage
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalMessage));
+ msg.optionalMessage = [Message2 message];
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalMessage));
+ msg.optionalMessage = nil;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalMessage));
+ [msg release];
+ }
+
//%PDDM-EXPAND-END PROTO2_TEST_HAS_FIELDS()
}
- (void)testProto3SingleFieldHasBehavior {
//
- // Setting to any value including the default value (0) should result has*
- // being true.
+ // Setting to any value but the default value (0) should result has*
+ // being true. When set to the default, shouldn't be true.
//
//%PDDM-DEFINE PROTO3_TEST_HAS_FIELD(FIELD, NON_ZERO_VALUE, ZERO_VALUE)
@@ -678,6 +755,17 @@
//% [msg release];
//% }
//%
+//%PDDM-DEFINE PROTO3_TEST_CLEAR_FIELD_WITH_NIL(FIELD, VALUE)
+//% { // optional##FIELD
+//% Message3 *msg = [[Message3 alloc] init];
+//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_Optional##FIELD));
+//% msg.optional##FIELD = VALUE;
+//% XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_Optional##FIELD));
+//% msg.optional##FIELD = nil;
+//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_Optional##FIELD));
+//% [msg release];
+//% }
+//%
//%PDDM-DEFINE PROTO3_TEST_HAS_FIELDS()
//%PROTO3_TEST_HAS_FIELD(Int32, 1, 0)
//%PROTO3_TEST_HAS_FIELD(Int64, 1, 0)
@@ -695,10 +783,17 @@
//%PROTO3_TEST_HAS_FIELD(String, @"foo", @"")
//%PROTO3_TEST_HAS_FIELD(Bytes, [@"foo" dataUsingEncoding:NSUTF8StringEncoding], [NSData data])
//% //
-//% // Test doesn't apply to optionalGroup/optionalMessage.
+//% // Test doesn't apply to optionalMessage (no groups in proto3).
//% //
//%
//%PROTO3_TEST_HAS_FIELD(Enum, Message3_Enum_Bar, Message3_Enum_Foo)
+//% //
+//% // Nil can also be used to clear strings, bytes, and messages (no groups in proto3).
+//% //
+//%
+//%PROTO3_TEST_CLEAR_FIELD_WITH_NIL(String, @"foo")
+//%PROTO3_TEST_CLEAR_FIELD_WITH_NIL(Bytes, [@"foo" dataUsingEncoding:NSUTF8StringEncoding])
+//%PROTO3_TEST_CLEAR_FIELD_WITH_NIL(Message, [Message3 message])
//%PDDM-EXPAND PROTO3_TEST_HAS_FIELDS()
// This block of code is generated, do not edit it directly.
@@ -853,7 +948,7 @@
}
//
- // Test doesn't apply to optionalGroup/optionalMessage.
+ // Test doesn't apply to optionalMessage (no groups in proto3).
//
{ // optionalEnum
@@ -866,6 +961,40 @@
[msg release];
}
+ //
+ // Nil can also be used to clear strings, bytes, and messages (no groups in proto3).
+ //
+
+ { // optionalString
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalString));
+ msg.optionalString = @"foo";
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalString));
+ msg.optionalString = nil;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalString));
+ [msg release];
+ }
+
+ { // optionalBytes
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBytes));
+ msg.optionalBytes = [@"foo" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBytes));
+ msg.optionalBytes = nil;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBytes));
+ [msg release];
+ }
+
+ { // optionalMessage
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalMessage));
+ msg.optionalMessage = [Message3 message];
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalMessage));
+ msg.optionalMessage = nil;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalMessage));
+ [msg release];
+ }
+
//%PDDM-EXPAND-END PROTO3_TEST_HAS_FIELDS()
}
@@ -1972,6 +2101,262 @@
[msg release];
}
+- (void)testProto2OneofSetToDefault {
+
+ // proto3 doesn't normally write out zero (default) fields, but if they are
+ // in a oneof it does. proto2 doesn't have this special behavior, but we
+ // still confirm setting to the explicit default does set the case to be
+ // sure the runtime is working correctly.
+
+ NSString *oneofStringDefault = @"string";
+ NSData *oneofBytesDefault = [@"data" dataUsingEncoding:NSUTF8StringEncoding];
+
+ Message2 *msg = [[Message2 alloc] init];
+
+ uint32_t values[] = {
+ Message2_O_OneOfCase_OneofInt32,
+ Message2_O_OneOfCase_OneofInt64,
+ Message2_O_OneOfCase_OneofUint32,
+ Message2_O_OneOfCase_OneofUint64,
+ Message2_O_OneOfCase_OneofSint32,
+ Message2_O_OneOfCase_OneofSint64,
+ Message2_O_OneOfCase_OneofFixed32,
+ Message2_O_OneOfCase_OneofFixed64,
+ Message2_O_OneOfCase_OneofSfixed32,
+ Message2_O_OneOfCase_OneofSfixed64,
+ Message2_O_OneOfCase_OneofFloat,
+ Message2_O_OneOfCase_OneofDouble,
+ Message2_O_OneOfCase_OneofBool,
+ Message2_O_OneOfCase_OneofString,
+ Message2_O_OneOfCase_OneofBytes,
+ // Skip group
+ // Skip message
+ Message2_O_OneOfCase_OneofEnum,
+ };
+
+ for (size_t i = 0; i < GPBARRAYSIZE(values); ++i) {
+ switch (values[i]) {
+ case Message2_O_OneOfCase_OneofInt32:
+ msg.oneofInt32 = 100;
+ break;
+ case Message2_O_OneOfCase_OneofInt64:
+ msg.oneofInt64 = 101;
+ break;
+ case Message2_O_OneOfCase_OneofUint32:
+ msg.oneofUint32 = 102;
+ break;
+ case Message2_O_OneOfCase_OneofUint64:
+ msg.oneofUint64 = 103;
+ break;
+ case Message2_O_OneOfCase_OneofSint32:
+ msg.oneofSint32 = 104;
+ break;
+ case Message2_O_OneOfCase_OneofSint64:
+ msg.oneofSint64 = 105;
+ break;
+ case Message2_O_OneOfCase_OneofFixed32:
+ msg.oneofFixed32 = 106;
+ break;
+ case Message2_O_OneOfCase_OneofFixed64:
+ msg.oneofFixed64 = 107;
+ break;
+ case Message2_O_OneOfCase_OneofSfixed32:
+ msg.oneofSfixed32 = 108;
+ break;
+ case Message2_O_OneOfCase_OneofSfixed64:
+ msg.oneofSfixed64 = 109;
+ break;
+ case Message2_O_OneOfCase_OneofFloat:
+ msg.oneofFloat = 110.0f;
+ break;
+ case Message2_O_OneOfCase_OneofDouble:
+ msg.oneofDouble = 111.0;
+ break;
+ case Message2_O_OneOfCase_OneofBool:
+ msg.oneofBool = YES;
+ break;
+ case Message2_O_OneOfCase_OneofString:
+ msg.oneofString = oneofStringDefault;
+ break;
+ case Message2_O_OneOfCase_OneofBytes:
+ msg.oneofBytes = oneofBytesDefault;
+ break;
+ case Message2_O_OneOfCase_OneofEnum:
+ msg.oneofEnum = Message3_Enum_Baz;
+ break;
+ default:
+ XCTFail(@"shouldn't happen, loop: %zd, value: %d", i, values[i]);
+ break;
+ }
+
+ // Should be set to the correct case.
+ XCTAssertEqual(msg.oOneOfCase, values[i], "Loop: %zd", i);
+
+ // Confirm everything is the defaults.
+ XCTAssertEqual(msg.oneofInt32, 100, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofInt64, 101, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofUint32, 102U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofUint64, 103U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSint32, 104, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSint64, 105, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFixed32, 106U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFixed64, 107U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSfixed32, 108, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSfixed64, 109, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFloat, 110.0f, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofDouble, 111.0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofBool, YES, "Loop: %zd", i);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault, "Loop: %zd", i);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault, "Loop: %zd", i);
+ // Skip group, no default to consider.
+ // Skip message, no default to consider.
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz, "Loop: %zd", i);
+ }
+
+ // We special case nil on string, data, group, and message, ensure they work
+ // as expected. i.e. - it clears the case.
+ msg.oneofString = nil;
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_GPBUnsetOneOfCase);
+ msg.oneofBytes = nil;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_GPBUnsetOneOfCase);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ msg.oneofGroup = nil;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_GPBUnsetOneOfCase);
+ XCTAssertNotNil(msg.oneofGroup);
+ msg.oneofMessage = nil;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_GPBUnsetOneOfCase);
+ XCTAssertNotNil(msg.oneofMessage);
+
+ [msg release];
+}
+
+- (void)testProto3OneofSetToZero {
+
+ // Normally setting a proto3 field to the zero value should result in it being
+ // reset/cleared. But in a oneof, it still gets recored so it can go out
+ // over the wire and the other side can see what was set in the oneof.
+
+ NSString *oneofStringDefault = @"";
+ NSData *oneofBytesDefault = [NSData data];
+
+ Message3 *msg = [[Message3 alloc] init];
+
+ uint32_t values[] = {
+ Message3_O_OneOfCase_OneofInt32,
+ Message3_O_OneOfCase_OneofInt64,
+ Message3_O_OneOfCase_OneofUint32,
+ Message3_O_OneOfCase_OneofUint64,
+ Message3_O_OneOfCase_OneofSint32,
+ Message3_O_OneOfCase_OneofSint64,
+ Message3_O_OneOfCase_OneofFixed32,
+ Message3_O_OneOfCase_OneofFixed64,
+ Message3_O_OneOfCase_OneofSfixed32,
+ Message3_O_OneOfCase_OneofSfixed64,
+ Message3_O_OneOfCase_OneofFloat,
+ Message3_O_OneOfCase_OneofDouble,
+ Message3_O_OneOfCase_OneofBool,
+ Message3_O_OneOfCase_OneofString,
+ Message3_O_OneOfCase_OneofBytes,
+ Message3_O_OneOfCase_OneofMessage,
+ Message3_O_OneOfCase_OneofEnum,
+ };
+
+ for (size_t i = 0; i < GPBARRAYSIZE(values); ++i) {
+ switch (values[i]) {
+ case Message3_O_OneOfCase_OneofInt32:
+ msg.oneofInt32 = 0;
+ break;
+ case Message3_O_OneOfCase_OneofInt64:
+ msg.oneofInt64 = 0;
+ break;
+ case Message3_O_OneOfCase_OneofUint32:
+ msg.oneofUint32 = 0;
+ break;
+ case Message3_O_OneOfCase_OneofUint64:
+ msg.oneofUint64 = 0;
+ break;
+ case Message3_O_OneOfCase_OneofSint32:
+ msg.oneofSint32 = 0;
+ break;
+ case Message3_O_OneOfCase_OneofSint64:
+ msg.oneofSint64 = 0;
+ break;
+ case Message3_O_OneOfCase_OneofFixed32:
+ msg.oneofFixed32 = 0;
+ break;
+ case Message3_O_OneOfCase_OneofFixed64:
+ msg.oneofFixed64 = 0;
+ break;
+ case Message3_O_OneOfCase_OneofSfixed32:
+ msg.oneofSfixed32 = 0;
+ break;
+ case Message3_O_OneOfCase_OneofSfixed64:
+ msg.oneofSfixed64 = 0;
+ break;
+ case Message3_O_OneOfCase_OneofFloat:
+ msg.oneofFloat = 0.0f;
+ break;
+ case Message3_O_OneOfCase_OneofDouble:
+ msg.oneofDouble = 0.0;
+ break;
+ case Message3_O_OneOfCase_OneofBool:
+ msg.oneofBool = NO;
+ break;
+ case Message3_O_OneOfCase_OneofString:
+ msg.oneofString = oneofStringDefault;
+ break;
+ case Message3_O_OneOfCase_OneofBytes:
+ msg.oneofBytes = oneofBytesDefault;
+ break;
+ case Message3_O_OneOfCase_OneofMessage:
+ msg.oneofMessage.optionalInt32 = 0;
+ break;
+ case Message3_O_OneOfCase_OneofEnum:
+ msg.oneofEnum = Message3_Enum_Foo;
+ break;
+ default:
+ XCTFail(@"shouldn't happen, loop: %zd, value: %d", i, values[i]);
+ break;
+ }
+
+ // Should be set to the correct case.
+ XCTAssertEqual(msg.oOneOfCase, values[i], "Loop: %zd", i);
+
+ // Confirm everything is still zeros.
+ XCTAssertEqual(msg.oneofInt32, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofInt64, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofUint32, 0U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofUint64, 0U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSint32, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSint64, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFixed32, 0U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFixed64, 0U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSfixed32, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSfixed64, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFloat, 0.0f, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofDouble, 0.0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofBool, NO, "Loop: %zd", i);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault, "Loop: %zd", i);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault, "Loop: %zd", i);
+ XCTAssertNotNil(msg.oneofMessage, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo, "Loop: %zd", i);
+ }
+
+ // We special case nil on string, data, message, ensure they work as expected.
+ msg.oneofString = nil;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_GPBUnsetOneOfCase);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ msg.oneofBytes = nil;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_GPBUnsetOneOfCase);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ msg.oneofMessage = nil;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_GPBUnsetOneOfCase);
+ XCTAssertNotNil(msg.oneofMessage);
+
+ [msg release];
+}
+
- (void)testCopyingMakesUniqueObjects {
const int repeatCount = 5;
TestAllTypes *msg1 = [TestAllTypes message];
diff --git a/objectivec/Tests/GPBUnittestProtos.m b/objectivec/Tests/GPBUnittestProtos.m
index d19beee9..8d2948bf 100644
--- a/objectivec/Tests/GPBUnittestProtos.m
+++ b/objectivec/Tests/GPBUnittestProtos.m
@@ -36,6 +36,7 @@
// a descriptor as it doesn't use the classes/enums.
#import "google/protobuf/Descriptor.pbobjc.m"
+#import "google/protobuf/AnyTest.pbobjc.m"
#import "google/protobuf/MapProto2Unittest.pbobjc.m"
#import "google/protobuf/MapUnittest.pbobjc.m"
#import "google/protobuf/Unittest.pbobjc.m"
@@ -62,3 +63,11 @@
#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.m"
#import "google/protobuf/UnittestRuntimeProto2.pbobjc.m"
#import "google/protobuf/UnittestRuntimeProto3.pbobjc.m"
+
+#import "google/protobuf/UnittestExtensionChainA.pbobjc.m"
+#import "google/protobuf/UnittestExtensionChainB.pbobjc.m"
+#import "google/protobuf/UnittestExtensionChainC.pbobjc.m"
+#import "google/protobuf/UnittestExtensionChainD.pbobjc.m"
+#import "google/protobuf/UnittestExtensionChainE.pbobjc.m"
+// See GPBUnittestProtos2.m for for "UnittestExtensionChainF.pbobjc.m"
+#import "google/protobuf/UnittestExtensionChainG.pbobjc.m"
diff --git a/csharp/src/Google.Protobuf.Conformance/Properties/AssemblyInfo.cs b/objectivec/Tests/GPBUnittestProtos2.m
index d22e90fd..ef9f0702 100644
--- a/csharp/src/Google.Protobuf.Conformance/Properties/AssemblyInfo.cs
+++ b/objectivec/Tests/GPBUnittestProtos2.m
@@ -1,6 +1,5 @@
-#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
-// Copyright 2015 Google Inc. All rights reserved.
+// Copyright 2016 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
@@ -28,21 +27,8 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-using System.Reflection;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Google.Protobuf.Conformance")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Google.Protobuf.Conformance")]
-[assembly: AssemblyCopyright("Copyright © 2015")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-[assembly: AssemblyVersion("3.0.0.0")]
-[assembly: AssemblyFileVersion("3.0.0.0")]
+// This one file in the chain tests is compiled by itself to ensure if was
+// generated with the extra #imports needed to pull in the indirect Root class
+// used in its Root registry.
+#import "google/protobuf/UnittestExtensionChainF.pbobjc.m"
diff --git a/objectivec/Tests/GPBWellKnownTypesTest.m b/objectivec/Tests/GPBWellKnownTypesTest.m
index 78f4e637..041841dd 100644
--- a/objectivec/Tests/GPBWellKnownTypesTest.m
+++ b/objectivec/Tests/GPBWellKnownTypesTest.m
@@ -32,6 +32,8 @@
#import <XCTest/XCTest.h>
+#import "google/protobuf/AnyTest.pbobjc.h"
+
// A basically random interval into the future for testing with.
static const NSTimeInterval kFutureOffsetInterval = 15000;
@@ -99,4 +101,58 @@ static const NSTimeInterval kTimeAccuracy = 1e-9;
[duration2 release];
}
+- (void)testAnyHelpers {
+
+ // Set and extract covers most of the code.
+
+ TestAny *subMessage = [TestAny message];
+ subMessage.int32Value = 12345;
+ TestAny *message = [TestAny message];
+ NSError *err = nil;
+ message.anyValue = [GPBAny anyWithMessage:subMessage error:&err];
+ XCTAssertNil(err);
+
+ NSData *data = message.data;
+ XCTAssertNotNil(data);
+
+ TestAny *message2 = [TestAny parseFromData:data error:&err];
+ XCTAssertNil(err);
+ XCTAssertNotNil(message2);
+ XCTAssertTrue(message2.hasAnyValue);
+
+ TestAny *subMessage2 =
+ (TestAny *)[message.anyValue unpackMessageClass:[TestAny class]
+ error:&err];
+ XCTAssertNil(err);
+ XCTAssertNotNil(subMessage2);
+ XCTAssertEqual(subMessage2.int32Value, 12345);
+
+ // NULL errorPtr in the two calls.
+
+ message.anyValue = [GPBAny anyWithMessage:subMessage error:NULL];
+ NSData *data2 = message.data;
+ XCTAssertEqualObjects(data2, data);
+
+ TestAny *subMessage3 =
+ (TestAny *)[message.anyValue unpackMessageClass:[TestAny class]
+ error:NULL];
+ XCTAssertNotNil(subMessage3);
+ XCTAssertEqualObjects(subMessage2, subMessage3);
+
+ // Try to extract wrong type.
+
+ GPBTimestamp *wrongMessage =
+ (GPBTimestamp *)[message.anyValue unpackMessageClass:[GPBTimestamp class]
+ error:&err];
+ XCTAssertNotNil(err);
+ XCTAssertNil(wrongMessage);
+ XCTAssertEqualObjects(err.domain, GPBWellKnownTypesErrorDomain);
+ XCTAssertEqual(err.code, GPBWellKnownTypesErrorCodeTypeURLMismatch);
+
+ wrongMessage =
+ (GPBTimestamp *)[message.anyValue unpackMessageClass:[GPBTimestamp class]
+ error:NULL];
+ XCTAssertNil(wrongMessage);
+}
+
@end
diff --git a/objectivec/Tests/unittest_cycle.proto b/objectivec/Tests/unittest_cycle.proto
index 5f6f56a1..afc1b0fe 100644
--- a/objectivec/Tests/unittest_cycle.proto
+++ b/objectivec/Tests/unittest_cycle.proto
@@ -31,10 +31,8 @@ syntax = "proto2";
package protobuf_unittest;
-// Cycles in the Message graph can cause problems for the mutable classes
-// since the properties on the mutable class change types. This file just
-// needs to generate source, and that source must compile, to ensure the
-// generated source works for this sort of case.
+// Cycles in the Message graph can cause problems for message class
+// initialization order.
// You can't make a object graph that spans files, so this can only be done
// within a single proto file.
diff --git a/objectivec/Tests/unittest_extension_chain_a.proto b/objectivec/Tests/unittest_extension_chain_a.proto
new file mode 100644
index 00000000..6a227eb9
--- /dev/null
+++ b/objectivec/Tests/unittest_extension_chain_a.proto
@@ -0,0 +1,51 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+import "google/protobuf/unittest.proto";
+
+import "unittest_extension_chain_b.proto";
+import "unittest_extension_chain_c.proto";
+import "unittest_extension_chain_d.proto";
+
+// The Root for this file should end up adding the local extension and merging
+// in the extensions from D's Root (unittest and C will come via D's).
+
+message ChainAMessage {
+ optional ChainBMessage b = 1;
+ optional ChainCMessage c = 2;
+ optional ChainDMessage d = 3;
+}
+
+extend TestAllExtensions {
+ optional int32 chain_a_extension = 10001;
+}
diff --git a/objectivec/Tests/unittest_extension_chain_b.proto b/objectivec/Tests/unittest_extension_chain_b.proto
new file mode 100644
index 00000000..0da7ed3e
--- /dev/null
+++ b/objectivec/Tests/unittest_extension_chain_b.proto
@@ -0,0 +1,47 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+import "google/protobuf/unittest.proto";
+
+import "unittest_extension_chain_c.proto";
+
+// The Root for this file should end up adding the local extension and merging
+// in the extensions from C's Root (unittest will come via C's).
+
+message ChainBMessage {
+ optional ChainCMessage c = 1;
+}
+
+extend TestAllExtensions {
+ optional int32 chain_b_extension = 10002;
+}
diff --git a/objectivec/Tests/unittest_extension_chain_c.proto b/objectivec/Tests/unittest_extension_chain_c.proto
new file mode 100644
index 00000000..c702900a
--- /dev/null
+++ b/objectivec/Tests/unittest_extension_chain_c.proto
@@ -0,0 +1,45 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+import "google/protobuf/unittest.proto";
+
+// The Root for this file should end up adding the local extension and merging
+// in the extensions from unittest.proto's Root.
+
+message ChainCMessage {
+ optional int32 my_field = 1;
+}
+
+extend TestAllExtensions {
+ optional int32 chain_c_extension = 10003;
+}
diff --git a/objectivec/Tests/unittest_extension_chain_d.proto b/objectivec/Tests/unittest_extension_chain_d.proto
new file mode 100644
index 00000000..f9abe3ba
--- /dev/null
+++ b/objectivec/Tests/unittest_extension_chain_d.proto
@@ -0,0 +1,49 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+import "google/protobuf/unittest.proto";
+
+import "unittest_extension_chain_b.proto";
+import "unittest_extension_chain_c.proto";
+
+// The root should end up needing to merge B (C will be merged into B, so it
+// doesn't need to be directly merged).
+
+message ChainDMessage {
+ optional ChainBMessage b = 1;
+ optional ChainCMessage c = 2;
+}
+
+extend TestAllExtensions {
+ optional int32 chain_d_extension = 10004;
+}
diff --git a/objectivec/Tests/unittest_extension_chain_e.proto b/objectivec/Tests/unittest_extension_chain_e.proto
new file mode 100644
index 00000000..fe116631
--- /dev/null
+++ b/objectivec/Tests/unittest_extension_chain_e.proto
@@ -0,0 +1,40 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+import "google/protobuf/unittest.proto";
+
+// The Root for this file should end up just merging in unittest's Root.
+
+message ChainEMessage {
+ optional TestAllTypes my_field = 1;
+}
diff --git a/objectivec/Tests/unittest_extension_chain_f.proto b/objectivec/Tests/unittest_extension_chain_f.proto
new file mode 100644
index 00000000..b9bed723
--- /dev/null
+++ b/objectivec/Tests/unittest_extension_chain_f.proto
@@ -0,0 +1,44 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+import "unittest_extension_chain_g.proto";
+
+// The Root for this file should just be merging in the extensions from C's
+// Root (because G doens't define anything itself).
+
+// The generated source will also have to directly import C's .h file so it can
+// compile the reference to C's Root class.
+
+message ChainFMessage {
+ optional ChainGMessage g = 1;
+}
diff --git a/objectivec/Tests/unittest_extension_chain_g.proto b/objectivec/Tests/unittest_extension_chain_g.proto
new file mode 100644
index 00000000..aee827b1
--- /dev/null
+++ b/objectivec/Tests/unittest_extension_chain_g.proto
@@ -0,0 +1,41 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+import "unittest_extension_chain_c.proto";
+
+// The Root for this file should just be merging in the extensions from C's
+// Root.
+
+message ChainGMessage {
+ optional ChainCMessage c = 1;
+}
diff --git a/objectivec/Tests/unittest_objc.proto b/objectivec/Tests/unittest_objc.proto
index 914945eb..e5577faf 100644
--- a/objectivec/Tests/unittest_objc.proto
+++ b/objectivec/Tests/unittest_objc.proto
@@ -34,6 +34,15 @@ import "google/protobuf/unittest.proto";
package protobuf_unittest;
+// Used to check that Headerdocs and appledoc work correctly. If these comments
+// are not handled correctly, Xcode will fail to build the tests.
+message TestGeneratedComments {
+ // This is a string that could contain stuff like
+ // mime types as image/* or */plain. Maybe twitter usernames
+ // like @protobuf, @google or @something.
+ optional string string_field = 1;
+}
+
// Using the messages in unittest.proto, setup for recursive cases for testing
// extensions at various depths.
extend TestAllExtensions {
diff --git a/objectivec/google/protobuf/Any.pbobjc.h b/objectivec/google/protobuf/Any.pbobjc.h
index 4253b604..b88b786a 100644
--- a/objectivec/google/protobuf/Any.pbobjc.h
+++ b/objectivec/google/protobuf/Any.pbobjc.h
@@ -13,7 +13,7 @@
#import "GPBProtocolBuffers.h"
#endif
-#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002
#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
@@ -28,14 +28,16 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - GPBAnyRoot
-/// Exposes the extension registry for this file.
-///
-/// The base class provides:
-/// @code
-/// + (GPBExtensionRegistry *)extensionRegistry;
-/// @endcode
-/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
-/// this file and all files that it depends on.
+/**
+ * Exposes the extension registry for this file.
+ *
+ * The base class provides:
+ * @code
+ * + (GPBExtensionRegistry *)extensionRegistry;
+ * @endcode
+ * which is a @c GPBExtensionRegistry that includes all the extensions defined by
+ * this file and all files that it depends on.
+ **/
@interface GPBAnyRoot : GPBRootObject
@end
@@ -46,101 +48,105 @@ typedef GPB_ENUM(GPBAny_FieldNumber) {
GPBAny_FieldNumber_Value = 2,
};
-/// `Any` contains an arbitrary serialized protocol buffer message along with a
-/// URL that describes the type of the serialized message.
-///
-/// Protobuf library provides support to pack/unpack Any values in the form
-/// of utility functions or additional generated methods of the Any type.
-///
-/// Example 1: Pack and unpack a message in C++.
-///
-/// Foo foo = ...;
-/// Any any;
-/// any.PackFrom(foo);
-/// ...
-/// if (any.UnpackTo(&foo)) {
-/// ...
-/// }
-///
-/// Example 2: Pack and unpack a message in Java.
-///
-/// Foo foo = ...;
-/// Any any = Any.pack(foo);
-/// ...
-/// if (any.is(Foo.class)) {
-/// foo = any.unpack(Foo.class);
-/// }
-///
-/// Example 3: Pack and unpack a message in Python.
-///
-/// foo = Foo(...)
-/// any = Any()
-/// any.Pack(foo)
-/// ...
-/// if any.Is(Foo.DESCRIPTOR):
-/// any.Unpack(foo)
-/// ...
-///
-/// The pack methods provided by protobuf library will by default use
-/// 'type.googleapis.com/full.type.name' as the type URL and the unpack
-/// methods only use the fully qualified type name after the last '/'
-/// in the type URL, for example "foo.bar.com/x/y.z" will yield type
-/// name "y.z".
-///
-///
-/// JSON
-/// ====
-/// The JSON representation of an `Any` value uses the regular
-/// representation of the deserialized, embedded message, with an
-/// additional field `\@type` which contains the type URL. Example:
-///
-/// package google.profile;
-/// message Person {
-/// string first_name = 1;
-/// string last_name = 2;
-/// }
-///
-/// {
-/// "\@type": "type.googleapis.com/google.profile.Person",
-/// "firstName": <string>,
-/// "lastName": <string>
-/// }
-///
-/// If the embedded message type is well-known and has a custom JSON
-/// representation, that representation will be embedded adding a field
-/// `value` which holds the custom JSON in addition to the `\@type`
-/// field. Example (for message [google.protobuf.Duration][]):
-///
-/// {
-/// "\@type": "type.googleapis.com/google.protobuf.Duration",
-/// "value": "1.212s"
-/// }
+/**
+ * `Any` contains an arbitrary serialized protocol buffer message along with a
+ * URL that describes the type of the serialized message.
+ *
+ * Protobuf library provides support to pack/unpack Any values in the form
+ * of utility functions or additional generated methods of the Any type.
+ *
+ * Example 1: Pack and unpack a message in C++.
+ *
+ * Foo foo = ...;
+ * Any any;
+ * any.PackFrom(foo);
+ * ...
+ * if (any.UnpackTo(&foo)) {
+ * ...
+ * }
+ *
+ * Example 2: Pack and unpack a message in Java.
+ *
+ * Foo foo = ...;
+ * Any any = Any.pack(foo);
+ * ...
+ * if (any.is(Foo.class)) {
+ * foo = any.unpack(Foo.class);
+ * }
+ *
+ * Example 3: Pack and unpack a message in Python.
+ *
+ * foo = Foo(...)
+ * any = Any()
+ * any.Pack(foo)
+ * ...
+ * if any.Is(Foo.DESCRIPTOR):
+ * any.Unpack(foo)
+ * ...
+ *
+ * The pack methods provided by protobuf library will by default use
+ * 'type.googleapis.com/full.type.name' as the type URL and the unpack
+ * methods only use the fully qualified type name after the last '/'
+ * in the type URL, for example "foo.bar.com/x/y.z" will yield type
+ * name "y.z".
+ *
+ *
+ * JSON
+ * ====
+ * The JSON representation of an `Any` value uses the regular
+ * representation of the deserialized, embedded message, with an
+ * additional field `\@type` which contains the type URL. Example:
+ *
+ * package google.profile;
+ * message Person {
+ * string first_name = 1;
+ * string last_name = 2;
+ * }
+ *
+ * {
+ * "\@type": "type.googleapis.com/google.profile.Person",
+ * "firstName": <string>,
+ * "lastName": <string>
+ * }
+ *
+ * If the embedded message type is well-known and has a custom JSON
+ * representation, that representation will be embedded adding a field
+ * `value` which holds the custom JSON in addition to the `\@type`
+ * field. Example (for message [google.protobuf.Duration][]):
+ *
+ * {
+ * "\@type": "type.googleapis.com/google.protobuf.Duration",
+ * "value": "1.212s"
+ * }
+ **/
@interface GPBAny : GPBMessage
-/// A URL/resource name whose content describes the type of the
-/// serialized protocol buffer message.
-///
-/// For URLs which use the scheme `http`, `https`, or no scheme, the
-/// following restrictions and interpretations apply:
-///
-/// * If no scheme is provided, `https` is assumed.
-/// * The last segment of the URL's path must represent the fully
-/// qualified name of the type (as in `path/google.protobuf.Duration`).
-/// The name should be in a canonical form (e.g., leading "." is
-/// not accepted).
-/// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
-/// value in binary format, or produce an error.
-/// * Applications are allowed to cache lookup results based on the
-/// URL, or have them precompiled into a binary to avoid any
-/// lookup. Therefore, binary compatibility needs to be preserved
-/// on changes to types. (Use versioned type names to manage
-/// breaking changes.)
-///
-/// Schemes other than `http`, `https` (or the empty scheme) might be
-/// used with implementation specific semantics.
+/**
+ * A URL/resource name whose content describes the type of the
+ * serialized protocol buffer message.
+ *
+ * For URLs which use the scheme `http`, `https`, or no scheme, the
+ * following restrictions and interpretations apply:
+ *
+ * * If no scheme is provided, `https` is assumed.
+ * * The last segment of the URL's path must represent the fully
+ * qualified name of the type (as in `path/google.protobuf.Duration`).
+ * The name should be in a canonical form (e.g., leading "." is
+ * not accepted).
+ * * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+ * value in binary format, or produce an error.
+ * * Applications are allowed to cache lookup results based on the
+ * URL, or have them precompiled into a binary to avoid any
+ * lookup. Therefore, binary compatibility needs to be preserved
+ * on changes to types. (Use versioned type names to manage
+ * breaking changes.)
+ *
+ * Schemes other than `http`, `https` (or the empty scheme) might be
+ * used with implementation specific semantics.
+ **/
@property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL;
-/// Must be a valid serialized protocol buffer of the above specified type.
+/** Must be a valid serialized protocol buffer of the above specified type. */
@property(nonatomic, readwrite, copy, null_resettable) NSData *value;
@end
diff --git a/objectivec/google/protobuf/Any.pbobjc.m b/objectivec/google/protobuf/Any.pbobjc.m
index 25e5b4c4..e1054926 100644
--- a/objectivec/google/protobuf/Any.pbobjc.m
+++ b/objectivec/google/protobuf/Any.pbobjc.m
@@ -27,6 +27,9 @@
@implementation GPBAnyRoot
+// No extensions in the file and no imports, so no need to generate
+// +extensionRegistry.
+
@end
#pragma mark - GPBAnyRoot_FileDescriptor
@@ -38,6 +41,7 @@ static GPBFileDescriptor *GPBAnyRoot_FileDescriptor(void) {
if (!descriptor) {
GPBDebugCheckRuntimeVersion();
descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+ objcPrefix:@"GPB"
syntax:GPBFileSyntaxProto3];
}
return descriptor;
@@ -68,7 +72,7 @@ typedef struct GPBAny__storage_ {
.number = GPBAny_FieldNumber_TypeURL,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBAny__storage_, typeURL),
- .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom,
+ .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom),
.dataType = GPBDataTypeString,
},
{
@@ -88,7 +92,7 @@ typedef struct GPBAny__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBAny__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
static const char *extraTextFormatInfo =
"\001\001\004\241!!\000";
diff --git a/objectivec/google/protobuf/Api.pbobjc.h b/objectivec/google/protobuf/Api.pbobjc.h
index 04341f47..3750e093 100644
--- a/objectivec/google/protobuf/Api.pbobjc.h
+++ b/objectivec/google/protobuf/Api.pbobjc.h
@@ -13,7 +13,7 @@
#import "GPBProtocolBuffers.h"
#endif
-#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002
#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
@@ -34,14 +34,16 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - GPBApiRoot
-/// Exposes the extension registry for this file.
-///
-/// The base class provides:
-/// @code
-/// + (GPBExtensionRegistry *)extensionRegistry;
-/// @endcode
-/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
-/// this file and all files that it depends on.
+/**
+ * Exposes the extension registry for this file.
+ *
+ * The base class provides:
+ * @code
+ * + (GPBExtensionRegistry *)extensionRegistry;
+ * @endcode
+ * which is a @c GPBExtensionRegistry that includes all the extensions defined by
+ * this file and all files that it depends on.
+ **/
@interface GPBApiRoot : GPBRootObject
@end
@@ -57,67 +59,79 @@ typedef GPB_ENUM(GPBApi_FieldNumber) {
GPBApi_FieldNumber_Syntax = 7,
};
-/// Api is a light-weight descriptor for a protocol buffer service.
+/**
+ * Api is a light-weight descriptor for a protocol buffer service.
+ **/
@interface GPBApi : GPBMessage
-/// The fully qualified name of this api, including package name
-/// followed by the api's simple name.
+/**
+ * The fully qualified name of this api, including package name
+ * followed by the api's simple name.
+ **/
@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
-/// The methods of this api, in unspecified order.
+/** The methods of this api, in unspecified order. */
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBMethod*> *methodsArray;
-/// The number of items in @c methodsArray without causing the array to be created.
+/** The number of items in @c methodsArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger methodsArray_Count;
-/// Any metadata attached to the API.
+/** Any metadata attached to the API. */
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
-/// The number of items in @c optionsArray without causing the array to be created.
+/** The number of items in @c optionsArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger optionsArray_Count;
-/// A version string for this api. If specified, must have the form
-/// `major-version.minor-version`, as in `1.10`. If the minor version
-/// is omitted, it defaults to zero. If the entire version field is
-/// empty, the major version is derived from the package name, as
-/// outlined below. If the field is not empty, the version in the
-/// package name will be verified to be consistent with what is
-/// provided here.
-///
-/// The versioning schema uses [semantic
-/// versioning](http://semver.org) where the major version number
-/// indicates a breaking change and the minor version an additive,
-/// non-breaking change. Both version numbers are signals to users
-/// what to expect from different versions, and should be carefully
-/// chosen based on the product plan.
-///
-/// The major version is also reflected in the package name of the
-/// API, which must end in `v<major-version>`, as in
-/// `google.feature.v1`. For major versions 0 and 1, the suffix can
-/// be omitted. Zero major versions must only be used for
-/// experimental, none-GA apis.
+/**
+ * A version string for this api. If specified, must have the form
+ * `major-version.minor-version`, as in `1.10`. If the minor version
+ * is omitted, it defaults to zero. If the entire version field is
+ * empty, the major version is derived from the package name, as
+ * outlined below. If the field is not empty, the version in the
+ * package name will be verified to be consistent with what is
+ * provided here.
+ *
+ * The versioning schema uses [semantic
+ * versioning](http://semver.org) where the major version number
+ * indicates a breaking change and the minor version an additive,
+ * non-breaking change. Both version numbers are signals to users
+ * what to expect from different versions, and should be carefully
+ * chosen based on the product plan.
+ *
+ * The major version is also reflected in the package name of the
+ * API, which must end in `v<major-version>`, as in
+ * `google.feature.v1`. For major versions 0 and 1, the suffix can
+ * be omitted. Zero major versions must only be used for
+ * experimental, none-GA apis.
+ **/
@property(nonatomic, readwrite, copy, null_resettable) NSString *version;
-/// Source context for the protocol buffer service represented by this
-/// message.
+/**
+ * Source context for the protocol buffer service represented by this
+ * message.
+ **/
@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext;
-/// Test to see if @c sourceContext has been set.
+/** Test to see if @c sourceContext has been set. */
@property(nonatomic, readwrite) BOOL hasSourceContext;
-/// Included APIs. See [Mixin][].
+/** Included APIs. See [Mixin][]. */
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBMixin*> *mixinsArray;
-/// The number of items in @c mixinsArray without causing the array to be created.
+/** The number of items in @c mixinsArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger mixinsArray_Count;
-/// The source syntax of the service.
+/** The source syntax of the service. */
@property(nonatomic, readwrite) enum GPBSyntax syntax;
@end
-/// Fetches the raw value of a @c GPBApi's @c syntax property, even
-/// if the value was not defined by the enum at the time the code was generated.
+/**
+ * Fetches the raw value of a @c GPBApi's @c syntax property, even
+ * if the value was not defined by the enum at the time the code was generated.
+ **/
int32_t GPBApi_Syntax_RawValue(GPBApi *message);
-/// Sets the raw value of an @c GPBApi's @c syntax property, allowing
-/// it to be set to a value that was not defined by the enum at the time the code
-/// was generated.
+/**
+ * Sets the raw value of an @c GPBApi's @c syntax property, allowing
+ * it to be set to a value that was not defined by the enum at the time the code
+ * was generated.
+ **/
void SetGPBApi_Syntax_RawValue(GPBApi *message, int32_t value);
#pragma mark - GPBMethod
@@ -132,40 +146,46 @@ typedef GPB_ENUM(GPBMethod_FieldNumber) {
GPBMethod_FieldNumber_Syntax = 7,
};
-/// Method represents a method of an api.
+/**
+ * Method represents a method of an api.
+ **/
@interface GPBMethod : GPBMessage
-/// The simple name of this method.
+/** The simple name of this method. */
@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
-/// A URL of the input message type.
+/** A URL of the input message type. */
@property(nonatomic, readwrite, copy, null_resettable) NSString *requestTypeURL;
-/// If true, the request is streamed.
+/** If true, the request is streamed. */
@property(nonatomic, readwrite) BOOL requestStreaming;
-/// The URL of the output message type.
+/** The URL of the output message type. */
@property(nonatomic, readwrite, copy, null_resettable) NSString *responseTypeURL;
-/// If true, the response is streamed.
+/** If true, the response is streamed. */
@property(nonatomic, readwrite) BOOL responseStreaming;
-/// Any metadata attached to the method.
+/** Any metadata attached to the method. */
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
-/// The number of items in @c optionsArray without causing the array to be created.
+/** The number of items in @c optionsArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger optionsArray_Count;
-/// The source syntax of this method.
+/** The source syntax of this method. */
@property(nonatomic, readwrite) enum GPBSyntax syntax;
@end
-/// Fetches the raw value of a @c GPBMethod's @c syntax property, even
-/// if the value was not defined by the enum at the time the code was generated.
+/**
+ * Fetches the raw value of a @c GPBMethod's @c syntax property, even
+ * if the value was not defined by the enum at the time the code was generated.
+ **/
int32_t GPBMethod_Syntax_RawValue(GPBMethod *message);
-/// Sets the raw value of an @c GPBMethod's @c syntax property, allowing
-/// it to be set to a value that was not defined by the enum at the time the code
-/// was generated.
+/**
+ * Sets the raw value of an @c GPBMethod's @c syntax property, allowing
+ * it to be set to a value that was not defined by the enum at the time the code
+ * was generated.
+ **/
void SetGPBMethod_Syntax_RawValue(GPBMethod *message, int32_t value);
#pragma mark - GPBMixin
@@ -175,90 +195,94 @@ typedef GPB_ENUM(GPBMixin_FieldNumber) {
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 {
-/// 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";
-/// }
-/// ...
-/// }
+/**
+ * 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 {
+ * 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.
+/** 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.
+/**
+ * If non-empty specifies a path under which inherited HTTP paths
+ * are rooted.
+ **/
@property(nonatomic, readwrite, copy, null_resettable) NSString *root;
@end
diff --git a/objectivec/google/protobuf/Api.pbobjc.m b/objectivec/google/protobuf/Api.pbobjc.m
index cd37edaa..70437d49 100644
--- a/objectivec/google/protobuf/Api.pbobjc.m
+++ b/objectivec/google/protobuf/Api.pbobjc.m
@@ -31,18 +31,8 @@
@implementation GPBApiRoot
-+ (GPBExtensionRegistry*)extensionRegistry {
- // This is called by +initialize so there is no need to worry
- // about thread safety and initialization of registry.
- static GPBExtensionRegistry* registry = nil;
- if (!registry) {
- GPBDebugCheckRuntimeVersion();
- registry = [[GPBExtensionRegistry alloc] init];
- [registry addExtensions:[GPBSourceContextRoot extensionRegistry]];
- [registry addExtensions:[GPBTypeRoot extensionRegistry]];
- }
- return registry;
-}
+// No extensions in the file and none of the imports (direct or indirect)
+// defined extensions, so no need to generate +extensionRegistry.
@end
@@ -55,6 +45,7 @@ static GPBFileDescriptor *GPBApiRoot_FileDescriptor(void) {
if (!descriptor) {
GPBDebugCheckRuntimeVersion();
descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+ objcPrefix:@"GPB"
syntax:GPBFileSyntaxProto3];
}
return descriptor;
@@ -149,7 +140,7 @@ typedef struct GPBApi__storage_ {
.number = GPBApi_FieldNumber_Syntax,
.hasIndex = 3,
.offset = (uint32_t)offsetof(GPBApi__storage_, syntax),
- .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+ .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
.dataType = GPBDataTypeEnum,
},
};
@@ -160,7 +151,7 @@ typedef struct GPBApi__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBApi__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
@@ -223,7 +214,7 @@ typedef struct GPBMethod__storage_ {
.number = GPBMethod_FieldNumber_RequestTypeURL,
.hasIndex = 1,
.offset = (uint32_t)offsetof(GPBMethod__storage_, requestTypeURL),
- .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom,
+ .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom),
.dataType = GPBDataTypeString,
},
{
@@ -241,7 +232,7 @@ typedef struct GPBMethod__storage_ {
.number = GPBMethod_FieldNumber_ResponseTypeURL,
.hasIndex = 4,
.offset = (uint32_t)offsetof(GPBMethod__storage_, responseTypeURL),
- .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom,
+ .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom),
.dataType = GPBDataTypeString,
},
{
@@ -268,7 +259,7 @@ typedef struct GPBMethod__storage_ {
.number = GPBMethod_FieldNumber_Syntax,
.hasIndex = 7,
.offset = (uint32_t)offsetof(GPBMethod__storage_, syntax),
- .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+ .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
.dataType = GPBDataTypeEnum,
},
};
@@ -279,7 +270,7 @@ typedef struct GPBMethod__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBMethod__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
static const char *extraTextFormatInfo =
"\002\002\007\244\241!!\000\004\010\244\241!!\000";
@@ -350,7 +341,7 @@ typedef struct GPBMixin__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBMixin__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
diff --git a/objectivec/google/protobuf/Duration.pbobjc.h b/objectivec/google/protobuf/Duration.pbobjc.h
index 4c3173d3..090eb002 100644
--- a/objectivec/google/protobuf/Duration.pbobjc.h
+++ b/objectivec/google/protobuf/Duration.pbobjc.h
@@ -13,7 +13,7 @@
#import "GPBProtocolBuffers.h"
#endif
-#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002
#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
@@ -28,14 +28,16 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - GPBDurationRoot
-/// Exposes the extension registry for this file.
-///
-/// The base class provides:
-/// @code
-/// + (GPBExtensionRegistry *)extensionRegistry;
-/// @endcode
-/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
-/// this file and all files that it depends on.
+/**
+ * Exposes the extension registry for this file.
+ *
+ * The base class provides:
+ * @code
+ * + (GPBExtensionRegistry *)extensionRegistry;
+ * @endcode
+ * which is a @c GPBExtensionRegistry that includes all the extensions defined by
+ * this file and all files that it depends on.
+ **/
@interface GPBDurationRoot : GPBRootObject
@end
@@ -46,58 +48,64 @@ typedef GPB_ENUM(GPBDuration_FieldNumber) {
GPBDuration_FieldNumber_Nanos = 2,
};
-/// A Duration represents a signed, fixed-length span of time represented
-/// as a count of seconds and fractions of seconds at nanosecond
-/// resolution. It is independent of any calendar and concepts like "day"
-/// or "month". It is related to Timestamp in that the difference between
-/// two Timestamp values is a Duration and it can be added or subtracted
-/// from a Timestamp. Range is approximately +-10,000 years.
-///
-/// Example 1: Compute Duration from two Timestamps in pseudo code.
-///
-/// Timestamp start = ...;
-/// Timestamp end = ...;
-/// Duration duration = ...;
-///
-/// duration.seconds = end.seconds - start.seconds;
-/// duration.nanos = end.nanos - start.nanos;
-///
-/// if (duration.seconds < 0 && duration.nanos > 0) {
-/// duration.seconds += 1;
-/// duration.nanos -= 1000000000;
-/// } else if (durations.seconds > 0 && duration.nanos < 0) {
-/// duration.seconds -= 1;
-/// duration.nanos += 1000000000;
-/// }
-///
-/// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
-///
-/// Timestamp start = ...;
-/// Duration duration = ...;
-/// Timestamp end = ...;
-///
-/// end.seconds = start.seconds + duration.seconds;
-/// end.nanos = start.nanos + duration.nanos;
-///
-/// if (end.nanos < 0) {
-/// end.seconds -= 1;
-/// end.nanos += 1000000000;
-/// } else if (end.nanos >= 1000000000) {
-/// end.seconds += 1;
-/// end.nanos -= 1000000000;
-/// }
+/**
+ * A Duration represents a signed, fixed-length span of time represented
+ * as a count of seconds and fractions of seconds at nanosecond
+ * resolution. It is independent of any calendar and concepts like "day"
+ * or "month". It is related to Timestamp in that the difference between
+ * two Timestamp values is a Duration and it can be added or subtracted
+ * from a Timestamp. Range is approximately +-10,000 years.
+ *
+ * Example 1: Compute Duration from two Timestamps in pseudo code.
+ *
+ * Timestamp start = ...;
+ * Timestamp end = ...;
+ * Duration duration = ...;
+ *
+ * duration.seconds = end.seconds - start.seconds;
+ * duration.nanos = end.nanos - start.nanos;
+ *
+ * if (duration.seconds < 0 && duration.nanos > 0) {
+ * duration.seconds += 1;
+ * duration.nanos -= 1000000000;
+ * } else if (durations.seconds > 0 && duration.nanos < 0) {
+ * duration.seconds -= 1;
+ * duration.nanos += 1000000000;
+ * }
+ *
+ * Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
+ *
+ * Timestamp start = ...;
+ * Duration duration = ...;
+ * Timestamp end = ...;
+ *
+ * end.seconds = start.seconds + duration.seconds;
+ * end.nanos = start.nanos + duration.nanos;
+ *
+ * if (end.nanos < 0) {
+ * end.seconds -= 1;
+ * end.nanos += 1000000000;
+ * } else if (end.nanos >= 1000000000) {
+ * end.seconds += 1;
+ * end.nanos -= 1000000000;
+ * }
+ **/
@interface GPBDuration : GPBMessage
-/// Signed seconds of the span of time. Must be from -315,576,000,000
-/// to +315,576,000,000 inclusive.
+/**
+ * Signed seconds of the span of time. Must be from -315,576,000,000
+ * to +315,576,000,000 inclusive.
+ **/
@property(nonatomic, readwrite) int64_t seconds;
-/// Signed fractions of a second at nanosecond resolution of the span
-/// of time. Durations less than one second are represented with a 0
-/// `seconds` field and a positive or negative `nanos` field. For durations
-/// of one second or more, a non-zero value for the `nanos` field must be
-/// of the same sign as the `seconds` field. Must be from -999,999,999
-/// to +999,999,999 inclusive.
+/**
+ * Signed fractions of a second at nanosecond resolution of the span
+ * of time. Durations less than one second are represented with a 0
+ * `seconds` field and a positive or negative `nanos` field. For durations
+ * of one second or more, a non-zero value for the `nanos` field must be
+ * of the same sign as the `seconds` field. Must be from -999,999,999
+ * to +999,999,999 inclusive.
+ **/
@property(nonatomic, readwrite) int32_t nanos;
@end
diff --git a/objectivec/google/protobuf/Duration.pbobjc.m b/objectivec/google/protobuf/Duration.pbobjc.m
index 35daa3df..f87d35db 100644
--- a/objectivec/google/protobuf/Duration.pbobjc.m
+++ b/objectivec/google/protobuf/Duration.pbobjc.m
@@ -27,6 +27,9 @@
@implementation GPBDurationRoot
+// No extensions in the file and no imports, so no need to generate
+// +extensionRegistry.
+
@end
#pragma mark - GPBDurationRoot_FileDescriptor
@@ -38,6 +41,7 @@ static GPBFileDescriptor *GPBDurationRoot_FileDescriptor(void) {
if (!descriptor) {
GPBDebugCheckRuntimeVersion();
descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+ objcPrefix:@"GPB"
syntax:GPBFileSyntaxProto3];
}
return descriptor;
@@ -88,7 +92,7 @@ typedef struct GPBDuration__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBDuration__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
diff --git a/objectivec/google/protobuf/Empty.pbobjc.h b/objectivec/google/protobuf/Empty.pbobjc.h
index 2d2a86bc..e0ed3e16 100644
--- a/objectivec/google/protobuf/Empty.pbobjc.h
+++ b/objectivec/google/protobuf/Empty.pbobjc.h
@@ -13,7 +13,7 @@
#import "GPBProtocolBuffers.h"
#endif
-#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002
#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
@@ -28,28 +28,32 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - GPBEmptyRoot
-/// Exposes the extension registry for this file.
-///
-/// The base class provides:
-/// @code
-/// + (GPBExtensionRegistry *)extensionRegistry;
-/// @endcode
-/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
-/// this file and all files that it depends on.
+/**
+ * Exposes the extension registry for this file.
+ *
+ * The base class provides:
+ * @code
+ * + (GPBExtensionRegistry *)extensionRegistry;
+ * @endcode
+ * which is a @c GPBExtensionRegistry that includes all the extensions defined by
+ * this file and all files that it depends on.
+ **/
@interface GPBEmptyRoot : GPBRootObject
@end
#pragma mark - GPBEmpty
-/// A generic empty message that you can re-use to avoid defining duplicated
-/// empty messages in your APIs. A typical example is to use it as the request
-/// or the response type of an API method. For instance:
-///
-/// service Foo {
-/// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
-/// }
-///
-/// The JSON representation for `Empty` is empty JSON object `{}`.
+/**
+ * A generic empty message that you can re-use to avoid defining duplicated
+ * empty messages in your APIs. A typical example is to use it as the request
+ * or the response type of an API method. For instance:
+ *
+ * service Foo {
+ * rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
+ * }
+ *
+ * The JSON representation for `Empty` is empty JSON object `{}`.
+ **/
@interface GPBEmpty : GPBMessage
@end
diff --git a/objectivec/google/protobuf/Empty.pbobjc.m b/objectivec/google/protobuf/Empty.pbobjc.m
index 1bdd4949..9b60f36d 100644
--- a/objectivec/google/protobuf/Empty.pbobjc.m
+++ b/objectivec/google/protobuf/Empty.pbobjc.m
@@ -27,6 +27,9 @@
@implementation GPBEmptyRoot
+// No extensions in the file and no imports, so no need to generate
+// +extensionRegistry.
+
@end
#pragma mark - GPBEmptyRoot_FileDescriptor
@@ -38,6 +41,7 @@ static GPBFileDescriptor *GPBEmptyRoot_FileDescriptor(void) {
if (!descriptor) {
GPBDebugCheckRuntimeVersion();
descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+ objcPrefix:@"GPB"
syntax:GPBFileSyntaxProto3];
}
return descriptor;
@@ -64,7 +68,7 @@ typedef struct GPBEmpty__storage_ {
fields:NULL
fieldCount:0
storageSize:sizeof(GPBEmpty__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.h b/objectivec/google/protobuf/FieldMask.pbobjc.h
index 06053f1a..14ed5379 100644
--- a/objectivec/google/protobuf/FieldMask.pbobjc.h
+++ b/objectivec/google/protobuf/FieldMask.pbobjc.h
@@ -13,7 +13,7 @@
#import "GPBProtocolBuffers.h"
#endif
-#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002
#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
@@ -28,14 +28,16 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - GPBFieldMaskRoot
-/// Exposes the extension registry for this file.
-///
-/// The base class provides:
-/// @code
-/// + (GPBExtensionRegistry *)extensionRegistry;
-/// @endcode
-/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
-/// this file and all files that it depends on.
+/**
+ * Exposes the extension registry for this file.
+ *
+ * The base class provides:
+ * @code
+ * + (GPBExtensionRegistry *)extensionRegistry;
+ * @endcode
+ * which is a @c GPBExtensionRegistry that includes all the extensions defined by
+ * this file and all files that it depends on.
+ **/
@interface GPBFieldMaskRoot : GPBRootObject
@end
@@ -45,212 +47,214 @@ typedef GPB_ENUM(GPBFieldMask_FieldNumber) {
GPBFieldMask_FieldNumber_PathsArray = 1,
};
-/// `FieldMask` represents a set of symbolic field paths, for example:
-///
-/// paths: "f.a"
-/// paths: "f.b.d"
-///
-/// Here `f` represents a field in some root message, `a` and `b`
-/// fields in the message found in `f`, and `d` a field found in the
-/// message in `f.b`.
-///
-/// Field masks are used to specify a subset of fields that should be
-/// returned by a get operation or modified by an update operation.
-/// Field masks also have a custom JSON encoding (see below).
-///
-/// # Field Masks in Projections
-///
-/// When used in the context of a projection, a response message or
-/// sub-message is filtered by the API to only contain those fields as
-/// specified in the mask. For example, if the mask in the previous
-/// example is applied to a response message as follows:
-///
-/// f {
-/// a : 22
-/// b {
-/// d : 1
-/// x : 2
-/// }
-/// y : 13
-/// }
-/// z: 8
-///
-/// The result will not contain specific values for fields x,y and z
-/// (their value will be set to the default, and omitted in proto text
-/// output):
-///
-///
-/// f {
-/// a : 22
-/// b {
-/// d : 1
-/// }
-/// }
-///
-/// A repeated field is not allowed except at the last position of a
-/// field mask.
-///
-/// If a FieldMask object is not present in a get operation, the
-/// operation applies to all fields (as if a FieldMask of all fields
-/// had been specified).
-///
-/// Note that a field mask does not necessarily apply to the
-/// top-level response message. In case of a REST get operation, the
-/// field mask applies directly to the response, but in case of a REST
-/// list operation, the mask instead applies to each individual message
-/// in the returned resource list. In case of a REST custom method,
-/// other definitions may be used. Where the mask applies will be
-/// clearly documented together with its declaration in the API. In
-/// any case, the effect on the returned resource/resources is required
-/// behavior for APIs.
-///
-/// # Field Masks in Update Operations
-///
-/// A field mask in update operations specifies which fields of the
-/// targeted resource are going to be updated. The API is required
-/// to only change the values of the fields as specified in the mask
-/// and leave the others untouched. If a resource is passed in to
-/// describe the updated values, the API ignores the values of all
-/// fields not covered by the mask.
-///
-/// If a repeated field is specified for an update operation, the existing
-/// repeated values in the target resource will be overwritten by the new values.
-/// Note that a repeated field is only allowed in the last position of a field
-/// mask.
-///
-/// If a sub-message is specified in the last position of the field mask for an
-/// update operation, then the existing sub-message in the target resource is
-/// overwritten. Given the target message:
-///
-/// f {
-/// b {
-/// d : 1
-/// x : 2
-/// }
-/// c : 1
-/// }
-///
-/// And an update message:
-///
-/// f {
-/// b {
-/// d : 10
-/// }
-/// }
-///
-/// then if the field mask is:
-///
-/// paths: "f.b"
-///
-/// then the result will be:
-///
-/// f {
-/// b {
-/// d : 10
-/// }
-/// c : 1
-/// }
-///
-/// However, if the update mask was:
-///
-/// paths: "f.b.d"
-///
-/// then the result would be:
-///
-/// f {
-/// b {
-/// d : 10
-/// x : 2
-/// }
-/// c : 1
-/// }
-///
-/// In order to reset a field's value to the default, the field must
-/// be in the mask and set to the default value in the provided resource.
-/// Hence, in order to reset all fields of a resource, provide a default
-/// instance of the resource and set all fields in the mask, or do
-/// not provide a mask as described below.
-///
-/// If a field mask is not present on update, the operation applies to
-/// all fields (as if a field mask of all fields has been specified).
-/// Note that in the presence of schema evolution, this may mean that
-/// fields the client does not know and has therefore not filled into
-/// the request will be reset to their default. If this is unwanted
-/// behavior, a specific service may require a client to always specify
-/// a field mask, producing an error if not.
-///
-/// As with get operations, the location of the resource which
-/// describes the updated values in the request message depends on the
-/// operation kind. In any case, the effect of the field mask is
-/// required to be honored by the API.
-///
-/// ## Considerations for HTTP REST
-///
-/// The HTTP kind of an update operation which uses a field mask must
-/// be set to PATCH instead of PUT in order to satisfy HTTP semantics
-/// (PUT must only be used for full updates).
-///
-/// # JSON Encoding of Field Masks
-///
-/// In JSON, a field mask is encoded as a single string where paths are
-/// separated by a comma. Fields name in each path are converted
-/// to/from lower-camel naming conventions.
-///
-/// As an example, consider the following message declarations:
-///
-/// message Profile {
-/// User user = 1;
-/// Photo photo = 2;
-/// }
-/// message User {
-/// string display_name = 1;
-/// string address = 2;
-/// }
-///
-/// In proto a field mask for `Profile` may look as such:
-///
-/// mask {
-/// paths: "user.display_name"
-/// paths: "photo"
-/// }
-///
-/// In JSON, the same mask is represented as below:
-///
-/// {
-/// mask: "user.displayName,photo"
-/// }
-///
-/// # Field Masks and Oneof Fields
-///
-/// Field masks treat fields in oneofs just as regular fields. Consider the
-/// following message:
-///
-/// message SampleMessage {
-/// oneof test_oneof {
-/// string name = 4;
-/// SubMessage sub_message = 9;
-/// }
-/// }
-///
-/// The field mask can be:
-///
-/// mask {
-/// paths: "name"
-/// }
-///
-/// Or:
-///
-/// mask {
-/// paths: "sub_message"
-/// }
-///
-/// Note that oneof type names ("test_oneof" in this case) cannot be used in
-/// paths.
+/**
+ * `FieldMask` represents a set of symbolic field paths, for example:
+ *
+ * paths: "f.a"
+ * paths: "f.b.d"
+ *
+ * Here `f` represents a field in some root message, `a` and `b`
+ * fields in the message found in `f`, and `d` a field found in the
+ * message in `f.b`.
+ *
+ * Field masks are used to specify a subset of fields that should be
+ * returned by a get operation or modified by an update operation.
+ * Field masks also have a custom JSON encoding (see below).
+ *
+ * # Field Masks in Projections
+ *
+ * When used in the context of a projection, a response message or
+ * sub-message is filtered by the API to only contain those fields as
+ * specified in the mask. For example, if the mask in the previous
+ * example is applied to a response message as follows:
+ *
+ * f {
+ * a : 22
+ * b {
+ * d : 1
+ * x : 2
+ * }
+ * y : 13
+ * }
+ * z: 8
+ *
+ * The result will not contain specific values for fields x,y and z
+ * (their value will be set to the default, and omitted in proto text
+ * output):
+ *
+ *
+ * f {
+ * a : 22
+ * b {
+ * d : 1
+ * }
+ * }
+ *
+ * A repeated field is not allowed except at the last position of a
+ * field mask.
+ *
+ * If a FieldMask object is not present in a get operation, the
+ * operation applies to all fields (as if a FieldMask of all fields
+ * had been specified).
+ *
+ * Note that a field mask does not necessarily apply to the
+ * top-level response message. In case of a REST get operation, the
+ * field mask applies directly to the response, but in case of a REST
+ * list operation, the mask instead applies to each individual message
+ * in the returned resource list. In case of a REST custom method,
+ * other definitions may be used. Where the mask applies will be
+ * clearly documented together with its declaration in the API. In
+ * any case, the effect on the returned resource/resources is required
+ * behavior for APIs.
+ *
+ * # Field Masks in Update Operations
+ *
+ * A field mask in update operations specifies which fields of the
+ * targeted resource are going to be updated. The API is required
+ * to only change the values of the fields as specified in the mask
+ * and leave the others untouched. If a resource is passed in to
+ * describe the updated values, the API ignores the values of all
+ * fields not covered by the mask.
+ *
+ * If a repeated field is specified for an update operation, the existing
+ * repeated values in the target resource will be overwritten by the new values.
+ * Note that a repeated field is only allowed in the last position of a field
+ * mask.
+ *
+ * If a sub-message is specified in the last position of the field mask for an
+ * update operation, then the existing sub-message in the target resource is
+ * overwritten. Given the target message:
+ *
+ * f {
+ * b {
+ * d : 1
+ * x : 2
+ * }
+ * c : 1
+ * }
+ *
+ * And an update message:
+ *
+ * f {
+ * b {
+ * d : 10
+ * }
+ * }
+ *
+ * then if the field mask is:
+ *
+ * paths: "f.b"
+ *
+ * then the result will be:
+ *
+ * f {
+ * b {
+ * d : 10
+ * }
+ * c : 1
+ * }
+ *
+ * However, if the update mask was:
+ *
+ * paths: "f.b.d"
+ *
+ * then the result would be:
+ *
+ * f {
+ * b {
+ * d : 10
+ * x : 2
+ * }
+ * c : 1
+ * }
+ *
+ * In order to reset a field's value to the default, the field must
+ * be in the mask and set to the default value in the provided resource.
+ * Hence, in order to reset all fields of a resource, provide a default
+ * instance of the resource and set all fields in the mask, or do
+ * not provide a mask as described below.
+ *
+ * If a field mask is not present on update, the operation applies to
+ * all fields (as if a field mask of all fields has been specified).
+ * Note that in the presence of schema evolution, this may mean that
+ * fields the client does not know and has therefore not filled into
+ * the request will be reset to their default. If this is unwanted
+ * behavior, a specific service may require a client to always specify
+ * a field mask, producing an error if not.
+ *
+ * As with get operations, the location of the resource which
+ * describes the updated values in the request message depends on the
+ * operation kind. In any case, the effect of the field mask is
+ * required to be honored by the API.
+ *
+ * ## Considerations for HTTP REST
+ *
+ * The HTTP kind of an update operation which uses a field mask must
+ * be set to PATCH instead of PUT in order to satisfy HTTP semantics
+ * (PUT must only be used for full updates).
+ *
+ * # JSON Encoding of Field Masks
+ *
+ * In JSON, a field mask is encoded as a single string where paths are
+ * separated by a comma. Fields name in each path are converted
+ * to/from lower-camel naming conventions.
+ *
+ * As an example, consider the following message declarations:
+ *
+ * message Profile {
+ * User user = 1;
+ * Photo photo = 2;
+ * }
+ * message User {
+ * string display_name = 1;
+ * string address = 2;
+ * }
+ *
+ * In proto a field mask for `Profile` may look as such:
+ *
+ * mask {
+ * paths: "user.display_name"
+ * paths: "photo"
+ * }
+ *
+ * In JSON, the same mask is represented as below:
+ *
+ * {
+ * mask: "user.displayName,photo"
+ * }
+ *
+ * # Field Masks and Oneof Fields
+ *
+ * Field masks treat fields in oneofs just as regular fields. Consider the
+ * following message:
+ *
+ * message SampleMessage {
+ * oneof test_oneof {
+ * string name = 4;
+ * SubMessage sub_message = 9;
+ * }
+ * }
+ *
+ * The field mask can be:
+ *
+ * mask {
+ * paths: "name"
+ * }
+ *
+ * Or:
+ *
+ * mask {
+ * paths: "sub_message"
+ * }
+ *
+ * Note that oneof type names ("test_oneof" in this case) cannot be used in
+ * paths.
+ **/
@interface GPBFieldMask : GPBMessage
-/// The set of field mask paths.
+/** The set of field mask paths. */
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<NSString*> *pathsArray;
-/// The number of items in @c pathsArray without causing the array to be created.
+/** The number of items in @c pathsArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger pathsArray_Count;
@end
diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.m b/objectivec/google/protobuf/FieldMask.pbobjc.m
index 2721fdfa..4dc8409c 100644
--- a/objectivec/google/protobuf/FieldMask.pbobjc.m
+++ b/objectivec/google/protobuf/FieldMask.pbobjc.m
@@ -27,6 +27,9 @@
@implementation GPBFieldMaskRoot
+// No extensions in the file and no imports, so no need to generate
+// +extensionRegistry.
+
@end
#pragma mark - GPBFieldMaskRoot_FileDescriptor
@@ -38,6 +41,7 @@ static GPBFileDescriptor *GPBFieldMaskRoot_FileDescriptor(void) {
if (!descriptor) {
GPBDebugCheckRuntimeVersion();
descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+ objcPrefix:@"GPB"
syntax:GPBFileSyntaxProto3];
}
return descriptor;
@@ -77,7 +81,7 @@ typedef struct GPBFieldMask__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBFieldMask__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.h b/objectivec/google/protobuf/SourceContext.pbobjc.h
index 4514fa9f..417562c0 100644
--- a/objectivec/google/protobuf/SourceContext.pbobjc.h
+++ b/objectivec/google/protobuf/SourceContext.pbobjc.h
@@ -13,7 +13,7 @@
#import "GPBProtocolBuffers.h"
#endif
-#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002
#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
@@ -28,14 +28,16 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - GPBSourceContextRoot
-/// Exposes the extension registry for this file.
-///
-/// The base class provides:
-/// @code
-/// + (GPBExtensionRegistry *)extensionRegistry;
-/// @endcode
-/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
-/// this file and all files that it depends on.
+/**
+ * Exposes the extension registry for this file.
+ *
+ * The base class provides:
+ * @code
+ * + (GPBExtensionRegistry *)extensionRegistry;
+ * @endcode
+ * which is a @c GPBExtensionRegistry that includes all the extensions defined by
+ * this file and all files that it depends on.
+ **/
@interface GPBSourceContextRoot : GPBRootObject
@end
@@ -45,12 +47,16 @@ typedef GPB_ENUM(GPBSourceContext_FieldNumber) {
GPBSourceContext_FieldNumber_FileName = 1,
};
-/// `SourceContext` represents information about the source of a
-/// protobuf element, like the file in which it is defined.
+/**
+ * `SourceContext` represents information about the source of a
+ * protobuf element, like the file in which it is defined.
+ **/
@interface GPBSourceContext : GPBMessage
-/// The path-qualified name of the .proto file that contained the associated
-/// protobuf element. For example: `"google/protobuf/source_context.proto"`.
+/**
+ * The path-qualified name of the .proto file that contained the associated
+ * protobuf element. For example: `"google/protobuf/source_context.proto"`.
+ **/
@property(nonatomic, readwrite, copy, null_resettable) NSString *fileName;
@end
diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.m b/objectivec/google/protobuf/SourceContext.pbobjc.m
index 6e3c9c07..648d736c 100644
--- a/objectivec/google/protobuf/SourceContext.pbobjc.m
+++ b/objectivec/google/protobuf/SourceContext.pbobjc.m
@@ -27,6 +27,9 @@
@implementation GPBSourceContextRoot
+// No extensions in the file and no imports, so no need to generate
+// +extensionRegistry.
+
@end
#pragma mark - GPBSourceContextRoot_FileDescriptor
@@ -38,6 +41,7 @@ static GPBFileDescriptor *GPBSourceContextRoot_FileDescriptor(void) {
if (!descriptor) {
GPBDebugCheckRuntimeVersion();
descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+ objcPrefix:@"GPB"
syntax:GPBFileSyntaxProto3];
}
return descriptor;
@@ -77,7 +81,7 @@ typedef struct GPBSourceContext__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBSourceContext__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
diff --git a/objectivec/google/protobuf/Struct.pbobjc.h b/objectivec/google/protobuf/Struct.pbobjc.h
index 3e2d55fd..163b39ba 100644
--- a/objectivec/google/protobuf/Struct.pbobjc.h
+++ b/objectivec/google/protobuf/Struct.pbobjc.h
@@ -13,7 +13,7 @@
#import "GPBProtocolBuffers.h"
#endif
-#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002
#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
@@ -32,35 +32,43 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Enum GPBNullValue
-/// `NullValue` is a singleton enumeration to represent the null value for the
-/// `Value` type union.
-///
-/// The JSON representation for `NullValue` is JSON `null`.
+/**
+ * `NullValue` is a singleton enumeration to represent the null value for the
+ * `Value` type union.
+ *
+ * The JSON representation for `NullValue` is JSON `null`.
+ **/
typedef GPB_ENUM(GPBNullValue) {
- /// Value used if any message's field encounters a value that is not defined
- /// by this enum. The message will also have C functions to get/set the rawValue
- /// of the field.
+ /**
+ * Value used if any message's field encounters a value that is not defined
+ * by this enum. The message will also have C functions to get/set the rawValue
+ * of the field.
+ **/
GPBNullValue_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,
- /// Null value.
+ /** Null value. */
GPBNullValue_NullValue = 0,
};
GPBEnumDescriptor *GPBNullValue_EnumDescriptor(void);
-/// Checks to see if the given value is defined by the enum or was not known at
-/// the time this source was generated.
+/**
+ * Checks to see if the given value is defined by the enum or was not known at
+ * the time this source was generated.
+ **/
BOOL GPBNullValue_IsValidValue(int32_t value);
#pragma mark - GPBStructRoot
-/// Exposes the extension registry for this file.
-///
-/// The base class provides:
-/// @code
-/// + (GPBExtensionRegistry *)extensionRegistry;
-/// @endcode
-/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
-/// this file and all files that it depends on.
+/**
+ * Exposes the extension registry for this file.
+ *
+ * The base class provides:
+ * @code
+ * + (GPBExtensionRegistry *)extensionRegistry;
+ * @endcode
+ * which is a @c GPBExtensionRegistry that includes all the extensions defined by
+ * this file and all files that it depends on.
+ **/
@interface GPBStructRoot : GPBRootObject
@end
@@ -70,19 +78,21 @@ typedef GPB_ENUM(GPBStruct_FieldNumber) {
GPBStruct_FieldNumber_Fields = 1,
};
-/// `Struct` represents a structured data value, consisting of fields
-/// which map to dynamically typed values. In some languages, `Struct`
-/// might be supported by a native representation. For example, in
-/// scripting languages like JS a struct is represented as an
-/// object. The details of that representation are described together
-/// with the proto support for the language.
-///
-/// The JSON representation for `Struct` is JSON object.
+/**
+ * `Struct` represents a structured data value, consisting of fields
+ * which map to dynamically typed values. In some languages, `Struct`
+ * might be supported by a native representation. For example, in
+ * scripting languages like JS a struct is represented as an
+ * object. The details of that representation are described together
+ * with the proto support for the language.
+ *
+ * The JSON representation for `Struct` is JSON object.
+ **/
@interface GPBStruct : GPBMessage
-/// Unordered map of dynamically typed values.
+/** Unordered map of dynamically typed values. */
@property(nonatomic, readwrite, strong, null_resettable) NSMutableDictionary<NSString*, GPBValue*> *fields;
-/// The number of items in @c fields without causing the array to be created.
+/** The number of items in @c fields without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger fields_Count;
@end
@@ -108,46 +118,54 @@ typedef GPB_ENUM(GPBValue_Kind_OneOfCase) {
GPBValue_Kind_OneOfCase_ListValue = 6,
};
-/// `Value` represents a dynamically typed value which can be either
-/// null, a number, a string, a boolean, a recursive struct value, or a
-/// list of values. A producer of value is expected to set one of that
-/// variants, absence of any variant indicates an error.
-///
-/// The JSON representation for `Value` is JSON value.
+/**
+ * `Value` represents a dynamically typed value which can be either
+ * null, a number, a string, a boolean, a recursive struct value, or a
+ * list of values. A producer of value is expected to set one of that
+ * variants, absence of any variant indicates an error.
+ *
+ * The JSON representation for `Value` is JSON value.
+ **/
@interface GPBValue : GPBMessage
-/// The kind of value.
+/** The kind of value. */
@property(nonatomic, readonly) GPBValue_Kind_OneOfCase kindOneOfCase;
-/// Represents a null value.
+/** Represents a null value. */
@property(nonatomic, readwrite) GPBNullValue nullValue;
-/// Represents a double value.
+/** Represents a double value. */
@property(nonatomic, readwrite) double numberValue;
-/// Represents a string value.
+/** Represents a string value. */
@property(nonatomic, readwrite, copy, null_resettable) NSString *stringValue;
-/// Represents a boolean value.
+/** Represents a boolean value. */
@property(nonatomic, readwrite) BOOL boolValue;
-/// Represents a structured value.
+/** Represents a structured value. */
@property(nonatomic, readwrite, strong, null_resettable) GPBStruct *structValue;
-/// Represents a repeated `Value`.
+/** Represents a repeated `Value`. */
@property(nonatomic, readwrite, strong, null_resettable) GPBListValue *listValue;
@end
-/// Fetches the raw value of a @c GPBValue's @c nullValue property, even
-/// if the value was not defined by the enum at the time the code was generated.
+/**
+ * Fetches the raw value of a @c GPBValue's @c nullValue property, even
+ * if the value was not defined by the enum at the time the code was generated.
+ **/
int32_t GPBValue_NullValue_RawValue(GPBValue *message);
-/// Sets the raw value of an @c GPBValue's @c nullValue property, allowing
-/// it to be set to a value that was not defined by the enum at the time the code
-/// was generated.
+/**
+ * Sets the raw value of an @c GPBValue's @c nullValue property, allowing
+ * it to be set to a value that was not defined by the enum at the time the code
+ * was generated.
+ **/
void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value);
-/// Clears whatever value was set for the oneof 'kind'.
+/**
+ * Clears whatever value was set for the oneof 'kind'.
+ **/
void GPBValue_ClearKindOneOfCase(GPBValue *message);
#pragma mark - GPBListValue
@@ -156,14 +174,16 @@ typedef GPB_ENUM(GPBListValue_FieldNumber) {
GPBListValue_FieldNumber_ValuesArray = 1,
};
-/// `ListValue` is a wrapper around a repeated field of values.
-///
-/// The JSON representation for `ListValue` is JSON array.
+/**
+ * `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.
+/** Repeated field of dynamically typed values. */
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBValue*> *valuesArray;
-/// The number of items in @c valuesArray without causing the array to be created.
+/** The number of items in @c valuesArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger valuesArray_Count;
@end
diff --git a/objectivec/google/protobuf/Struct.pbobjc.m b/objectivec/google/protobuf/Struct.pbobjc.m
index 538faab3..bc9f23ff 100644
--- a/objectivec/google/protobuf/Struct.pbobjc.m
+++ b/objectivec/google/protobuf/Struct.pbobjc.m
@@ -28,6 +28,9 @@
@implementation GPBStructRoot
+// No extensions in the file and no imports, so no need to generate
+// +extensionRegistry.
+
@end
#pragma mark - GPBStructRoot_FileDescriptor
@@ -39,6 +42,7 @@ static GPBFileDescriptor *GPBStructRoot_FileDescriptor(void) {
if (!descriptor) {
GPBDebugCheckRuntimeVersion();
descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+ objcPrefix:@"GPB"
syntax:GPBFileSyntaxProto3];
}
return descriptor;
@@ -110,7 +114,7 @@ typedef struct GPBStruct__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBStruct__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
@@ -152,7 +156,7 @@ typedef struct GPBValue__storage_ {
.number = GPBValue_FieldNumber_NullValue,
.hasIndex = -1,
.offset = (uint32_t)offsetof(GPBValue__storage_, nullValue),
- .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+ .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
.dataType = GPBDataTypeEnum,
},
{
@@ -208,7 +212,7 @@ typedef struct GPBValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBValue__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
static const char *oneofs[] = {
"kind",
};
@@ -237,7 +241,7 @@ void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value) {
void GPBValue_ClearKindOneOfCase(GPBValue *message) {
GPBDescriptor *descriptor = [message descriptor];
- GPBOneofDescriptor *oneof = descriptor->oneofs_[0];
+ GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0];
GPBMaybeClearOneof(message, oneof, -1, 0);
}
#pragma mark - GPBListValue
@@ -274,7 +278,7 @@ typedef struct GPBListValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBListValue__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.h b/objectivec/google/protobuf/Timestamp.pbobjc.h
index d15de7c7..094e9b6b 100644
--- a/objectivec/google/protobuf/Timestamp.pbobjc.h
+++ b/objectivec/google/protobuf/Timestamp.pbobjc.h
@@ -13,7 +13,7 @@
#import "GPBProtocolBuffers.h"
#endif
-#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002
#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
@@ -28,14 +28,16 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - GPBTimestampRoot
-/// Exposes the extension registry for this file.
-///
-/// The base class provides:
-/// @code
-/// + (GPBExtensionRegistry *)extensionRegistry;
-/// @endcode
-/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
-/// this file and all files that it depends on.
+/**
+ * Exposes the extension registry for this file.
+ *
+ * The base class provides:
+ * @code
+ * + (GPBExtensionRegistry *)extensionRegistry;
+ * @endcode
+ * which is a @c GPBExtensionRegistry that includes all the extensions defined by
+ * this file and all files that it depends on.
+ **/
@interface GPBTimestampRoot : GPBRootObject
@end
@@ -46,70 +48,76 @@ typedef GPB_ENUM(GPBTimestamp_FieldNumber) {
GPBTimestamp_FieldNumber_Nanos = 2,
};
-/// A Timestamp represents a point in time independent of any time zone
-/// or calendar, represented as seconds and fractions of seconds at
-/// nanosecond resolution in UTC Epoch time. It is encoded using the
-/// Proleptic Gregorian Calendar which extends the Gregorian calendar
-/// backwards to year one. It is encoded assuming all minutes are 60
-/// seconds long, i.e. leap seconds are "smeared" so that no leap second
-/// table is needed for interpretation. Range is from
-/// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
-/// By restricting to that range, we ensure that we can convert to
-/// and from RFC 3339 date strings.
-/// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
-///
-/// Example 1: Compute Timestamp from POSIX `time()`.
-///
-/// Timestamp timestamp;
-/// timestamp.set_seconds(time(NULL));
-/// timestamp.set_nanos(0);
-///
-/// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
-///
-/// struct timeval tv;
-/// gettimeofday(&tv, NULL);
-///
-/// Timestamp timestamp;
-/// timestamp.set_seconds(tv.tv_sec);
-/// timestamp.set_nanos(tv.tv_usec * 1000);
-///
-/// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
-///
-/// FILETIME ft;
-/// GetSystemTimeAsFileTime(&ft);
-/// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
-///
-/// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
-/// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
-/// Timestamp timestamp;
-/// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
-/// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
-///
-/// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
-///
-/// long millis = System.currentTimeMillis();
-///
-/// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
-/// .setNanos((int) ((millis % 1000) * 1000000)).build();
-///
-///
-/// Example 5: Compute Timestamp from current time in Python.
-///
-/// now = time.time()
-/// seconds = int(now)
-/// nanos = int((now - seconds) * 10**9)
-/// timestamp = Timestamp(seconds=seconds, nanos=nanos)
+/**
+ * A Timestamp represents a point in time independent of any time zone
+ * or calendar, represented as seconds and fractions of seconds at
+ * nanosecond resolution in UTC Epoch time. It is encoded using the
+ * Proleptic Gregorian Calendar which extends the Gregorian calendar
+ * backwards to year one. It is encoded assuming all minutes are 60
+ * seconds long, i.e. leap seconds are "smeared" so that no leap second
+ * table is needed for interpretation. Range is from
+ * 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
+ * By restricting to that range, we ensure that we can convert to
+ * and from RFC 3339 date strings.
+ * See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
+ *
+ * Example 1: Compute Timestamp from POSIX `time()`.
+ *
+ * Timestamp timestamp;
+ * timestamp.set_seconds(time(NULL));
+ * timestamp.set_nanos(0);
+ *
+ * Example 2: Compute Timestamp from POSIX `gettimeofday()`.
+ *
+ * struct timeval tv;
+ * gettimeofday(&tv, NULL);
+ *
+ * Timestamp timestamp;
+ * timestamp.set_seconds(tv.tv_sec);
+ * timestamp.set_nanos(tv.tv_usec * 1000);
+ *
+ * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+ *
+ * FILETIME ft;
+ * GetSystemTimeAsFileTime(&ft);
+ * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+ *
+ * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+ * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+ * Timestamp timestamp;
+ * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+ * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+ *
+ * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
+ *
+ * long millis = System.currentTimeMillis();
+ *
+ * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+ * .setNanos((int) ((millis % 1000) * 1000000)).build();
+ *
+ *
+ * Example 5: Compute Timestamp from current time in Python.
+ *
+ * now = time.time()
+ * seconds = int(now)
+ * nanos = int((now - seconds) * 10**9)
+ * timestamp = Timestamp(seconds=seconds, nanos=nanos)
+ **/
@interface GPBTimestamp : GPBMessage
-/// 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.
+/**
+ * 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.
+ **/
@property(nonatomic, readwrite) int64_t seconds;
-/// Non-negative fractions of a second at nanosecond resolution. Negative
-/// second values with fractions must still have non-negative nanos values
-/// that count forward in time. Must be from 0 to 999,999,999
-/// inclusive.
+/**
+ * Non-negative fractions of a second at nanosecond resolution. Negative
+ * second values with fractions must still have non-negative nanos values
+ * that count forward in time. Must be from 0 to 999,999,999
+ * inclusive.
+ **/
@property(nonatomic, readwrite) int32_t nanos;
@end
diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.m b/objectivec/google/protobuf/Timestamp.pbobjc.m
index 06e3ef94..1506dff3 100644
--- a/objectivec/google/protobuf/Timestamp.pbobjc.m
+++ b/objectivec/google/protobuf/Timestamp.pbobjc.m
@@ -27,6 +27,9 @@
@implementation GPBTimestampRoot
+// No extensions in the file and no imports, so no need to generate
+// +extensionRegistry.
+
@end
#pragma mark - GPBTimestampRoot_FileDescriptor
@@ -38,6 +41,7 @@ static GPBFileDescriptor *GPBTimestampRoot_FileDescriptor(void) {
if (!descriptor) {
GPBDebugCheckRuntimeVersion();
descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+ objcPrefix:@"GPB"
syntax:GPBFileSyntaxProto3];
}
return descriptor;
@@ -88,7 +92,7 @@ typedef struct GPBTimestamp__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBTimestamp__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
diff --git a/objectivec/google/protobuf/Type.pbobjc.h b/objectivec/google/protobuf/Type.pbobjc.h
index 93ee3cec..da923c30 100644
--- a/objectivec/google/protobuf/Type.pbobjc.h
+++ b/objectivec/google/protobuf/Type.pbobjc.h
@@ -13,7 +13,7 @@
#import "GPBProtocolBuffers.h"
#endif
-#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002
#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
@@ -34,134 +34,148 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Enum GPBSyntax
-/// The syntax in which a protocol buffer element is defined.
+/** The syntax in which a protocol buffer element is defined. */
typedef GPB_ENUM(GPBSyntax) {
- /// Value used if any message's field encounters a value that is not defined
- /// by this enum. The message will also have C functions to get/set the rawValue
- /// of the field.
+ /**
+ * Value used if any message's field encounters a value that is not defined
+ * by this enum. The message will also have C functions to get/set the rawValue
+ * of the field.
+ **/
GPBSyntax_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,
- /// Syntax `proto2`.
+ /** Syntax `proto2`. */
GPBSyntax_SyntaxProto2 = 0,
- /// Syntax `proto3`.
+ /** Syntax `proto3`. */
GPBSyntax_SyntaxProto3 = 1,
};
GPBEnumDescriptor *GPBSyntax_EnumDescriptor(void);
-/// Checks to see if the given value is defined by the enum or was not known at
-/// the time this source was generated.
+/**
+ * Checks to see if the given value is defined by the enum or was not known at
+ * the time this source was generated.
+ **/
BOOL GPBSyntax_IsValidValue(int32_t value);
#pragma mark - Enum GPBField_Kind
-/// Basic field types.
+/** Basic field types. */
typedef GPB_ENUM(GPBField_Kind) {
- /// Value used if any message's field encounters a value that is not defined
- /// by this enum. The message will also have C functions to get/set the rawValue
- /// of the field.
+ /**
+ * Value used if any message's field encounters a value that is not defined
+ * by this enum. The message will also have C functions to get/set the rawValue
+ * of the field.
+ **/
GPBField_Kind_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,
- /// Field type unknown.
+ /** Field type unknown. */
GPBField_Kind_TypeUnknown = 0,
- /// Field type double.
+ /** Field type double. */
GPBField_Kind_TypeDouble = 1,
- /// Field type float.
+ /** Field type float. */
GPBField_Kind_TypeFloat = 2,
- /// Field type int64.
+ /** Field type int64. */
GPBField_Kind_TypeInt64 = 3,
- /// Field type uint64.
+ /** Field type uint64. */
GPBField_Kind_TypeUint64 = 4,
- /// Field type int32.
+ /** Field type int32. */
GPBField_Kind_TypeInt32 = 5,
- /// Field type fixed64.
+ /** Field type fixed64. */
GPBField_Kind_TypeFixed64 = 6,
- /// Field type fixed32.
+ /** Field type fixed32. */
GPBField_Kind_TypeFixed32 = 7,
- /// Field type bool.
+ /** Field type bool. */
GPBField_Kind_TypeBool = 8,
- /// Field type string.
+ /** Field type string. */
GPBField_Kind_TypeString = 9,
- /// Field type group. Proto2 syntax only, and deprecated.
+ /** Field type group. Proto2 syntax only, and deprecated. */
GPBField_Kind_TypeGroup = 10,
- /// Field type message.
+ /** Field type message. */
GPBField_Kind_TypeMessage = 11,
- /// Field type bytes.
+ /** Field type bytes. */
GPBField_Kind_TypeBytes = 12,
- /// Field type uint32.
+ /** Field type uint32. */
GPBField_Kind_TypeUint32 = 13,
- /// Field type enum.
+ /** Field type enum. */
GPBField_Kind_TypeEnum = 14,
- /// Field type sfixed32.
+ /** Field type sfixed32. */
GPBField_Kind_TypeSfixed32 = 15,
- /// Field type sfixed64.
+ /** Field type sfixed64. */
GPBField_Kind_TypeSfixed64 = 16,
- /// Field type sint32.
+ /** Field type sint32. */
GPBField_Kind_TypeSint32 = 17,
- /// Field type sint64.
+ /** Field type sint64. */
GPBField_Kind_TypeSint64 = 18,
};
GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void);
-/// Checks to see if the given value is defined by the enum or was not known at
-/// the time this source was generated.
+/**
+ * Checks to see if the given value is defined by the enum or was not known at
+ * the time this source was generated.
+ **/
BOOL GPBField_Kind_IsValidValue(int32_t value);
#pragma mark - Enum GPBField_Cardinality
-/// Whether a field is optional, required, or repeated.
+/** Whether a field is optional, required, or repeated. */
typedef GPB_ENUM(GPBField_Cardinality) {
- /// Value used if any message's field encounters a value that is not defined
- /// by this enum. The message will also have C functions to get/set the rawValue
- /// of the field.
+ /**
+ * Value used if any message's field encounters a value that is not defined
+ * by this enum. The message will also have C functions to get/set the rawValue
+ * of the field.
+ **/
GPBField_Cardinality_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,
- /// For fields with unknown cardinality.
+ /** For fields with unknown cardinality. */
GPBField_Cardinality_CardinalityUnknown = 0,
- /// For optional fields.
+ /** For optional fields. */
GPBField_Cardinality_CardinalityOptional = 1,
- /// For required fields. Proto2 syntax only.
+ /** For required fields. Proto2 syntax only. */
GPBField_Cardinality_CardinalityRequired = 2,
- /// For repeated fields.
+ /** For repeated fields. */
GPBField_Cardinality_CardinalityRepeated = 3,
};
GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void);
-/// Checks to see if the given value is defined by the enum or was not known at
-/// the time this source was generated.
+/**
+ * Checks to see if the given value is defined by the enum or was not known at
+ * the time this source was generated.
+ **/
BOOL GPBField_Cardinality_IsValidValue(int32_t value);
#pragma mark - GPBTypeRoot
-/// Exposes the extension registry for this file.
-///
-/// The base class provides:
-/// @code
-/// + (GPBExtensionRegistry *)extensionRegistry;
-/// @endcode
-/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
-/// this file and all files that it depends on.
+/**
+ * Exposes the extension registry for this file.
+ *
+ * The base class provides:
+ * @code
+ * + (GPBExtensionRegistry *)extensionRegistry;
+ * @endcode
+ * which is a @c GPBExtensionRegistry that includes all the extensions defined by
+ * this file and all files that it depends on.
+ **/
@interface GPBTypeRoot : GPBRootObject
@end
@@ -176,43 +190,49 @@ typedef GPB_ENUM(GPBType_FieldNumber) {
GPBType_FieldNumber_Syntax = 6,
};
-/// A protocol buffer message type.
+/**
+ * A protocol buffer message type.
+ **/
@interface GPBType : GPBMessage
-/// The fully qualified message name.
+/** The fully qualified message name. */
@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
-/// The list of fields.
+/** The list of fields. */
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBField*> *fieldsArray;
-/// The number of items in @c fieldsArray without causing the array to be created.
+/** The number of items in @c fieldsArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger fieldsArray_Count;
-/// The list of types appearing in `oneof` definitions in this type.
+/** The list of types appearing in `oneof` definitions in this type. */
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<NSString*> *oneofsArray;
-/// The number of items in @c oneofsArray without causing the array to be created.
+/** The number of items in @c oneofsArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger oneofsArray_Count;
-/// The protocol buffer options.
+/** The protocol buffer options. */
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
-/// The number of items in @c optionsArray without causing the array to be created.
+/** The number of items in @c optionsArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger optionsArray_Count;
-/// The source context.
+/** The source context. */
@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext;
-/// Test to see if @c sourceContext has been set.
+/** Test to see if @c sourceContext has been set. */
@property(nonatomic, readwrite) BOOL hasSourceContext;
-/// The source syntax.
+/** The source syntax. */
@property(nonatomic, readwrite) GPBSyntax syntax;
@end
-/// Fetches the raw value of a @c GPBType's @c syntax property, even
-/// if the value was not defined by the enum at the time the code was generated.
+/**
+ * Fetches the raw value of a @c GPBType's @c syntax property, even
+ * if the value was not defined by the enum at the time the code was generated.
+ **/
int32_t GPBType_Syntax_RawValue(GPBType *message);
-/// Sets the raw value of an @c GPBType's @c syntax property, allowing
-/// it to be set to a value that was not defined by the enum at the time the code
-/// was generated.
+/**
+ * Sets the raw value of an @c GPBType's @c syntax property, allowing
+ * it to be set to a value that was not defined by the enum at the time the code
+ * was generated.
+ **/
void SetGPBType_Syntax_RawValue(GPBType *message, int32_t value);
#pragma mark - GPBField
@@ -230,59 +250,73 @@ typedef GPB_ENUM(GPBField_FieldNumber) {
GPBField_FieldNumber_DefaultValue = 11,
};
-/// A single field of a message type.
+/**
+ * A single field of a message type.
+ **/
@interface GPBField : GPBMessage
-/// The field type.
+/** The field type. */
@property(nonatomic, readwrite) GPBField_Kind kind;
-/// The field cardinality.
+/** The field cardinality. */
@property(nonatomic, readwrite) GPBField_Cardinality cardinality;
-/// The field number.
+/** The field number. */
@property(nonatomic, readwrite) int32_t number;
-/// The field name.
+/** The field name. */
@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
-/// The field type URL, without the scheme, for message or enumeration
-/// types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`.
+/**
+ * The field type URL, without the scheme, for message or enumeration
+ * types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`.
+ **/
@property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL;
-/// The index of the field type in `Type.oneofs`, for message or enumeration
-/// types. The first type has index 1; zero means the type is not in the list.
+/**
+ * The index of the field type in `Type.oneofs`, for message or enumeration
+ * types. The first type has index 1; zero means the type is not in the list.
+ **/
@property(nonatomic, readwrite) int32_t oneofIndex;
-/// Whether to use alternative packed wire representation.
+/** Whether to use alternative packed wire representation. */
@property(nonatomic, readwrite) BOOL packed;
-/// The protocol buffer options.
+/** The protocol buffer options. */
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
-/// The number of items in @c optionsArray without causing the array to be created.
+/** The number of items in @c optionsArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger optionsArray_Count;
-/// The field JSON name.
+/** The field JSON name. */
@property(nonatomic, readwrite, copy, null_resettable) NSString *jsonName;
-/// The string value of the default value of this field. Proto2 syntax only.
+/** The string value of the default value of this field. Proto2 syntax only. */
@property(nonatomic, readwrite, copy, null_resettable) NSString *defaultValue;
@end
-/// Fetches the raw value of a @c GPBField's @c kind property, even
-/// if the value was not defined by the enum at the time the code was generated.
+/**
+ * Fetches the raw value of a @c GPBField's @c kind property, even
+ * if the value was not defined by the enum at the time the code was generated.
+ **/
int32_t GPBField_Kind_RawValue(GPBField *message);
-/// Sets the raw value of an @c GPBField's @c kind property, allowing
-/// it to be set to a value that was not defined by the enum at the time the code
-/// was generated.
+/**
+ * Sets the raw value of an @c GPBField's @c kind property, allowing
+ * it to be set to a value that was not defined by the enum at the time the code
+ * was generated.
+ **/
void SetGPBField_Kind_RawValue(GPBField *message, int32_t value);
-/// Fetches the raw value of a @c GPBField's @c cardinality property, even
-/// if the value was not defined by the enum at the time the code was generated.
+/**
+ * Fetches the raw value of a @c GPBField's @c cardinality property, even
+ * if the value was not defined by the enum at the time the code was generated.
+ **/
int32_t GPBField_Cardinality_RawValue(GPBField *message);
-/// Sets the raw value of an @c GPBField's @c cardinality property, allowing
-/// it to be set to a value that was not defined by the enum at the time the code
-/// was generated.
+/**
+ * Sets the raw value of an @c GPBField's @c cardinality property, allowing
+ * it to be set to a value that was not defined by the enum at the time the code
+ * was generated.
+ **/
void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value);
#pragma mark - GPBEnum
@@ -295,38 +329,44 @@ typedef GPB_ENUM(GPBEnum_FieldNumber) {
GPBEnum_FieldNumber_Syntax = 5,
};
-/// Enum type definition.
+/**
+ * Enum type definition.
+ **/
@interface GPBEnum : GPBMessage
-/// Enum type name.
+/** Enum type name. */
@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
-/// Enum value definitions.
+/** Enum value definitions. */
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBEnumValue*> *enumvalueArray;
-/// The number of items in @c enumvalueArray without causing the array to be created.
+/** The number of items in @c enumvalueArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger enumvalueArray_Count;
-/// Protocol buffer options.
+/** Protocol buffer options. */
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
-/// The number of items in @c optionsArray without causing the array to be created.
+/** The number of items in @c optionsArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger optionsArray_Count;
-/// The source context.
+/** The source context. */
@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext;
-/// Test to see if @c sourceContext has been set.
+/** Test to see if @c sourceContext has been set. */
@property(nonatomic, readwrite) BOOL hasSourceContext;
-/// The source syntax.
+/** The source syntax. */
@property(nonatomic, readwrite) GPBSyntax syntax;
@end
-/// Fetches the raw value of a @c GPBEnum's @c syntax property, even
-/// if the value was not defined by the enum at the time the code was generated.
+/**
+ * Fetches the raw value of a @c GPBEnum's @c syntax property, even
+ * if the value was not defined by the enum at the time the code was generated.
+ **/
int32_t GPBEnum_Syntax_RawValue(GPBEnum *message);
-/// Sets the raw value of an @c GPBEnum's @c syntax property, allowing
-/// it to be set to a value that was not defined by the enum at the time the code
-/// was generated.
+/**
+ * Sets the raw value of an @c GPBEnum's @c syntax property, allowing
+ * it to be set to a value that was not defined by the enum at the time the code
+ * was generated.
+ **/
void SetGPBEnum_Syntax_RawValue(GPBEnum *message, int32_t value);
#pragma mark - GPBEnumValue
@@ -337,18 +377,20 @@ typedef GPB_ENUM(GPBEnumValue_FieldNumber) {
GPBEnumValue_FieldNumber_OptionsArray = 3,
};
-/// Enum value definition.
+/**
+ * Enum value definition.
+ **/
@interface GPBEnumValue : GPBMessage
-/// Enum value name.
+/** Enum value name. */
@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
-/// Enum value number.
+/** Enum value number. */
@property(nonatomic, readwrite) int32_t number;
-/// Protocol buffer options.
+/** Protocol buffer options. */
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
-/// The number of items in @c optionsArray without causing the array to be created.
+/** The number of items in @c optionsArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger optionsArray_Count;
@end
@@ -360,16 +402,18 @@ typedef GPB_ENUM(GPBOption_FieldNumber) {
GPBOption_FieldNumber_Value = 2,
};
-/// A protocol buffer option, which can be attached to a message, field,
-/// enumeration, etc.
+/**
+ * A protocol buffer option, which can be attached to a message, field,
+ * enumeration, etc.
+ **/
@interface GPBOption : GPBMessage
-/// The option's name. For example, `"java_package"`.
+/** The option's name. For example, `"java_package"`. */
@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
-/// The option's value. For example, `"com.google.protobuf"`.
+/** The option's value. For example, `"com.google.protobuf"`. */
@property(nonatomic, readwrite, strong, null_resettable) GPBAny *value;
-/// Test to see if @c value has been set.
+/** Test to see if @c value has been set. */
@property(nonatomic, readwrite) BOOL hasValue;
@end
diff --git a/objectivec/google/protobuf/Type.pbobjc.m b/objectivec/google/protobuf/Type.pbobjc.m
index 6c7b4efd..a36f1cd4 100644
--- a/objectivec/google/protobuf/Type.pbobjc.m
+++ b/objectivec/google/protobuf/Type.pbobjc.m
@@ -31,18 +31,8 @@
@implementation GPBTypeRoot
-+ (GPBExtensionRegistry*)extensionRegistry {
- // This is called by +initialize so there is no need to worry
- // about thread safety and initialization of registry.
- static GPBExtensionRegistry* registry = nil;
- if (!registry) {
- GPBDebugCheckRuntimeVersion();
- registry = [[GPBExtensionRegistry alloc] init];
- [registry addExtensions:[GPBAnyRoot extensionRegistry]];
- [registry addExtensions:[GPBSourceContextRoot extensionRegistry]];
- }
- return registry;
-}
+// No extensions in the file and none of the imports (direct or indirect)
+// defined extensions, so no need to generate +extensionRegistry.
@end
@@ -55,6 +45,7 @@ static GPBFileDescriptor *GPBTypeRoot_FileDescriptor(void) {
if (!descriptor) {
GPBDebugCheckRuntimeVersion();
descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+ objcPrefix:@"GPB"
syntax:GPBFileSyntaxProto3];
}
return descriptor;
@@ -172,7 +163,7 @@ typedef struct GPBType__storage_ {
.number = GPBType_FieldNumber_Syntax,
.hasIndex = 2,
.offset = (uint32_t)offsetof(GPBType__storage_, syntax),
- .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+ .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
.dataType = GPBDataTypeEnum,
},
};
@@ -183,7 +174,7 @@ typedef struct GPBType__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBType__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
@@ -244,7 +235,7 @@ typedef struct GPBField__storage_ {
.number = GPBField_FieldNumber_Kind,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBField__storage_, kind),
- .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+ .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
.dataType = GPBDataTypeEnum,
},
{
@@ -253,7 +244,7 @@ typedef struct GPBField__storage_ {
.number = GPBField_FieldNumber_Cardinality,
.hasIndex = 1,
.offset = (uint32_t)offsetof(GPBField__storage_, cardinality),
- .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+ .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
.dataType = GPBDataTypeEnum,
},
{
@@ -280,7 +271,7 @@ typedef struct GPBField__storage_ {
.number = GPBField_FieldNumber_TypeURL,
.hasIndex = 4,
.offset = (uint32_t)offsetof(GPBField__storage_, typeURL),
- .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom,
+ .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom),
.dataType = GPBDataTypeString,
},
{
@@ -336,7 +327,7 @@ typedef struct GPBField__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBField__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
static const char *extraTextFormatInfo =
"\001\006\004\241!!\000";
@@ -553,7 +544,7 @@ typedef struct GPBEnum__storage_ {
.number = GPBEnum_FieldNumber_Syntax,
.hasIndex = 2,
.offset = (uint32_t)offsetof(GPBEnum__storage_, syntax),
- .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+ .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
.dataType = GPBDataTypeEnum,
},
};
@@ -564,7 +555,7 @@ typedef struct GPBEnum__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBEnum__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
@@ -641,7 +632,7 @@ typedef struct GPBEnumValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBEnumValue__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
@@ -695,7 +686,7 @@ typedef struct GPBOption__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBOption__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.h b/objectivec/google/protobuf/Wrappers.pbobjc.h
index 5593d348..2bf6fd29 100644
--- a/objectivec/google/protobuf/Wrappers.pbobjc.h
+++ b/objectivec/google/protobuf/Wrappers.pbobjc.h
@@ -13,7 +13,7 @@
#import "GPBProtocolBuffers.h"
#endif
-#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002
#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
@@ -28,14 +28,16 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - GPBWrappersRoot
-/// Exposes the extension registry for this file.
-///
-/// The base class provides:
-/// @code
-/// + (GPBExtensionRegistry *)extensionRegistry;
-/// @endcode
-/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
-/// this file and all files that it depends on.
+/**
+ * Exposes the extension registry for this file.
+ *
+ * The base class provides:
+ * @code
+ * + (GPBExtensionRegistry *)extensionRegistry;
+ * @endcode
+ * which is a @c GPBExtensionRegistry that includes all the extensions defined by
+ * this file and all files that it depends on.
+ **/
@interface GPBWrappersRoot : GPBRootObject
@end
@@ -45,12 +47,14 @@ typedef GPB_ENUM(GPBDoubleValue_FieldNumber) {
GPBDoubleValue_FieldNumber_Value = 1,
};
-/// Wrapper message for `double`.
-///
-/// The JSON representation for `DoubleValue` is JSON number.
+/**
+ * Wrapper message for `double`.
+ *
+ * The JSON representation for `DoubleValue` is JSON number.
+ **/
@interface GPBDoubleValue : GPBMessage
-/// The double value.
+/** The double value. */
@property(nonatomic, readwrite) double value;
@end
@@ -61,12 +65,14 @@ typedef GPB_ENUM(GPBFloatValue_FieldNumber) {
GPBFloatValue_FieldNumber_Value = 1,
};
-/// Wrapper message for `float`.
-///
-/// The JSON representation for `FloatValue` is JSON number.
+/**
+ * Wrapper message for `float`.
+ *
+ * The JSON representation for `FloatValue` is JSON number.
+ **/
@interface GPBFloatValue : GPBMessage
-/// The float value.
+/** The float value. */
@property(nonatomic, readwrite) float value;
@end
@@ -77,12 +83,14 @@ typedef GPB_ENUM(GPBInt64Value_FieldNumber) {
GPBInt64Value_FieldNumber_Value = 1,
};
-/// Wrapper message for `int64`.
-///
-/// The JSON representation for `Int64Value` is JSON string.
+/**
+ * Wrapper message for `int64`.
+ *
+ * The JSON representation for `Int64Value` is JSON string.
+ **/
@interface GPBInt64Value : GPBMessage
-/// The int64 value.
+/** The int64 value. */
@property(nonatomic, readwrite) int64_t value;
@end
@@ -93,12 +101,14 @@ typedef GPB_ENUM(GPBUInt64Value_FieldNumber) {
GPBUInt64Value_FieldNumber_Value = 1,
};
-/// Wrapper message for `uint64`.
-///
-/// The JSON representation for `UInt64Value` is JSON string.
+/**
+ * Wrapper message for `uint64`.
+ *
+ * The JSON representation for `UInt64Value` is JSON string.
+ **/
@interface GPBUInt64Value : GPBMessage
-/// The uint64 value.
+/** The uint64 value. */
@property(nonatomic, readwrite) uint64_t value;
@end
@@ -109,12 +119,14 @@ typedef GPB_ENUM(GPBInt32Value_FieldNumber) {
GPBInt32Value_FieldNumber_Value = 1,
};
-/// Wrapper message for `int32`.
-///
-/// The JSON representation for `Int32Value` is JSON number.
+/**
+ * Wrapper message for `int32`.
+ *
+ * The JSON representation for `Int32Value` is JSON number.
+ **/
@interface GPBInt32Value : GPBMessage
-/// The int32 value.
+/** The int32 value. */
@property(nonatomic, readwrite) int32_t value;
@end
@@ -125,12 +137,14 @@ typedef GPB_ENUM(GPBUInt32Value_FieldNumber) {
GPBUInt32Value_FieldNumber_Value = 1,
};
-/// Wrapper message for `uint32`.
-///
-/// The JSON representation for `UInt32Value` is JSON number.
+/**
+ * Wrapper message for `uint32`.
+ *
+ * The JSON representation for `UInt32Value` is JSON number.
+ **/
@interface GPBUInt32Value : GPBMessage
-/// The uint32 value.
+/** The uint32 value. */
@property(nonatomic, readwrite) uint32_t value;
@end
@@ -141,12 +155,14 @@ typedef GPB_ENUM(GPBBoolValue_FieldNumber) {
GPBBoolValue_FieldNumber_Value = 1,
};
-/// Wrapper message for `bool`.
-///
-/// The JSON representation for `BoolValue` is JSON `true` and `false`.
+/**
+ * Wrapper message for `bool`.
+ *
+ * The JSON representation for `BoolValue` is JSON `true` and `false`.
+ **/
@interface GPBBoolValue : GPBMessage
-/// The bool value.
+/** The bool value. */
@property(nonatomic, readwrite) BOOL value;
@end
@@ -157,12 +173,14 @@ typedef GPB_ENUM(GPBStringValue_FieldNumber) {
GPBStringValue_FieldNumber_Value = 1,
};
-/// Wrapper message for `string`.
-///
-/// The JSON representation for `StringValue` is JSON string.
+/**
+ * Wrapper message for `string`.
+ *
+ * The JSON representation for `StringValue` is JSON string.
+ **/
@interface GPBStringValue : GPBMessage
-/// The string value.
+/** The string value. */
@property(nonatomic, readwrite, copy, null_resettable) NSString *value;
@end
@@ -173,12 +191,14 @@ typedef GPB_ENUM(GPBBytesValue_FieldNumber) {
GPBBytesValue_FieldNumber_Value = 1,
};
-/// Wrapper message for `bytes`.
-///
-/// The JSON representation for `BytesValue` is JSON string.
+/**
+ * Wrapper message for `bytes`.
+ *
+ * The JSON representation for `BytesValue` is JSON string.
+ **/
@interface GPBBytesValue : GPBMessage
-/// The bytes value.
+/** The bytes value. */
@property(nonatomic, readwrite, copy, null_resettable) NSData *value;
@end
diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.m b/objectivec/google/protobuf/Wrappers.pbobjc.m
index b5405a7d..c8fdeb08 100644
--- a/objectivec/google/protobuf/Wrappers.pbobjc.m
+++ b/objectivec/google/protobuf/Wrappers.pbobjc.m
@@ -27,6 +27,9 @@
@implementation GPBWrappersRoot
+// No extensions in the file and no imports, so no need to generate
+// +extensionRegistry.
+
@end
#pragma mark - GPBWrappersRoot_FileDescriptor
@@ -38,6 +41,7 @@ static GPBFileDescriptor *GPBWrappersRoot_FileDescriptor(void) {
if (!descriptor) {
GPBDebugCheckRuntimeVersion();
descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+ objcPrefix:@"GPB"
syntax:GPBFileSyntaxProto3];
}
return descriptor;
@@ -77,7 +81,7 @@ typedef struct GPBDoubleValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBDoubleValue__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
@@ -120,7 +124,7 @@ typedef struct GPBFloatValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBFloatValue__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
@@ -163,7 +167,7 @@ typedef struct GPBInt64Value__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBInt64Value__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
@@ -206,7 +210,7 @@ typedef struct GPBUInt64Value__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBUInt64Value__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
@@ -249,7 +253,7 @@ typedef struct GPBInt32Value__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBInt32Value__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
@@ -292,7 +296,7 @@ typedef struct GPBUInt32Value__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBUInt32Value__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
@@ -334,7 +338,7 @@ typedef struct GPBBoolValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBBoolValue__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
@@ -377,7 +381,7 @@ typedef struct GPBStringValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBStringValue__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
@@ -420,7 +424,7 @@ typedef struct GPBBytesValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBBytesValue__storage_)
- flags:0];
+ flags:GPBDescriptorInitializationFlag_None];
NSAssert(descriptor == nil, @"Startup recursed!");
descriptor = localDescriptor;
}
diff --git a/protobuf.bzl b/protobuf.bzl
index c5555fde..e356f53c 100644
--- a/protobuf.bzl
+++ b/protobuf.bzl
@@ -62,9 +62,19 @@ def _proto_gen_impl(ctx):
if ctx.attr.gen_py:
args += ["--python_out=" + ctx.var["GENDIR"] + "/" + gen_dir]
- if ctx.executable.grpc_cpp_plugin:
- args += ["--plugin=protoc-gen-grpc=" + ctx.executable.grpc_cpp_plugin.path]
- args += ["--grpc_out=" + ctx.var["GENDIR"] + "/" + gen_dir]
+ if ctx.executable.plugin:
+ plugin = ctx.executable.plugin
+ lang = ctx.attr.plugin_language
+ if not lang and plugin.basename.startswith('protoc-gen-'):
+ lang = plugin.basename[len('protoc-gen-'):]
+ if not lang:
+ fail("cannot infer the target language of plugin", "plugin_language")
+
+ outdir = ctx.var["GENDIR"] + "/" + gen_dir
+ if ctx.attr.plugin_options:
+ outdir = ",".join(ctx.attr.plugin_options) + ":" + outdir
+ args += ["--plugin=protoc-gen-%s=%s" % (lang, plugin.path)]
+ args += ["--%s_out=%s" % (lang, outdir)]
if args:
ctx.action(
@@ -72,6 +82,7 @@ def _proto_gen_impl(ctx):
outputs=ctx.outputs.outs,
arguments=args + import_flags + [s.path for s in srcs],
executable=ctx.executable.protoc,
+ mnemonic="ProtoCompile",
)
return struct(
@@ -82,22 +93,24 @@ def _proto_gen_impl(ctx):
),
)
-_proto_gen = rule(
+proto_gen = rule(
attrs = {
"srcs": attr.label_list(allow_files = True),
"deps": attr.label_list(providers = ["proto"]),
"includes": attr.string_list(),
"protoc": attr.label(
- cfg = HOST_CFG,
+ cfg = "host",
executable = True,
single_file = True,
mandatory = True,
),
- "grpc_cpp_plugin": attr.label(
- cfg = HOST_CFG,
+ "plugin": attr.label(
+ cfg = "host",
+ allow_files = True,
executable = True,
- single_file = True,
),
+ "plugin_language": attr.string(),
+ "plugin_options": attr.string_list(),
"gen_cc": attr.bool(),
"gen_py": attr.bool(),
"outs": attr.output_list(),
@@ -105,6 +118,26 @@ _proto_gen = rule(
output_to_genfiles = True,
implementation = _proto_gen_impl,
)
+"""Generates codes from Protocol Buffers definitions.
+
+This rule helps you to implement Skylark macros specific to the target
+language. You should prefer more specific `cc_proto_library `,
+`py_proto_library` and others unless you are adding such wrapper macros.
+
+Args:
+ srcs: Protocol Buffers definition files (.proto) to run the protocol compiler
+ against.
+ deps: a list of dependency labels; must be other proto libraries.
+ includes: a list of include paths to .proto files.
+ protoc: the label of the protocol compiler to generate the sources.
+ plugin: the label of the protocol compiler plugin to be passed to the protocol
+ compiler.
+ plugin_language: the language of the generated sources
+ plugin_options: a list of options to be passed to the plugin
+ gen_cc: generates C++ sources in addition to the ones from the plugin.
+ gen_py: generates Python sources in addition to the ones from the plugin.
+ outs: a list of labels of the expected outputs from the protocol compiler.
+"""
def cc_proto_library(
name,
@@ -150,7 +183,7 @@ def cc_proto_library(
if internal_bootstrap_hack:
# For pre-checked-in generated files, we add the internal_bootstrap_hack
# which will skip the codegen action.
- _proto_gen(
+ proto_gen(
name=name + "_genproto",
srcs=srcs,
deps=[s + "_genproto" for s in deps],
@@ -170,13 +203,14 @@ def cc_proto_library(
outs = _CcOuts(srcs, use_grpc_plugin)
- _proto_gen(
+ proto_gen(
name=name + "_genproto",
srcs=srcs,
deps=[s + "_genproto" for s in deps],
includes=includes,
protoc=protoc,
- grpc_cpp_plugin=grpc_cpp_plugin,
+ plugin=grpc_cpp_plugin,
+ plugin_language="grpc",
gen_cc=1,
outs=outs,
visibility=["//visibility:public"],
@@ -286,7 +320,7 @@ def py_proto_library(
if include != None:
includes = [include]
- _proto_gen(
+ proto_gen(
name=name + "_genproto",
srcs=srcs,
deps=[s + "_genproto" for s in deps],
diff --git a/protoc-artifacts/Dockerfile b/protoc-artifacts/Dockerfile
index fd35b89f..5143b028 100644
--- a/protoc-artifacts/Dockerfile
+++ b/protoc-artifacts/Dockerfile
@@ -21,9 +21,9 @@ ENV JAVA_HOME /var/local/jdk1.8.0_45
ENV PATH $JAVA_HOME/bin:$PATH
# Install Maven
-RUN wget -q http://apache.cs.utah.edu/maven/maven-3/3.3.3/binaries/apache-maven-3.3.3-bin.tar.gz -O - | \
+RUN wget -q http://apache.cs.utah.edu/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz -O - | \
tar xz -C /var/local
-ENV PATH /var/local/apache-maven-3.3.3/bin:$PATH
+ENV PATH /var/local/apache-maven-3.3.9/bin:$PATH
# Install GCC 4.7 to support -static-libstdc++
RUN wget http://people.centos.org/tru/devtools-1.1/devtools-1.1.repo -P /etc/yum.repos.d
diff --git a/protoc-artifacts/README.md b/protoc-artifacts/README.md
index a910fe0d..50629209 100644
--- a/protoc-artifacts/README.md
+++ b/protoc-artifacts/README.md
@@ -102,6 +102,25 @@ When you have done deployment for all platforms, go to
https://oss.sonatype.org/#stagingRepositories, verify that the staging
repository has all the binaries, close and release this repository.
+## Upload zip packages to github release page.
+After uploading protoc artifacts to Maven Central repository, run the
+build-zip.sh script to bulid zip packages for these protoc binaries
+and upload these zip packages to the download section of the github
+release. For example:
+```
+$ ./build-zip.sh 3.0.0-beta-4
+```
+The above command will create 5 zip files:
+```
+dist/protoc-3.0.0-beta-4-win32.zip
+dist/protoc-3.0.0-beta-4-osx-x86_32.zip
+dist/protoc-3.0.0-beta-4-osx-x86_64.zip
+dist/protoc-3.0.0-beta-4-linux-x86_32.zip
+dist/protoc-3.0.0-beta-4-linux-x86_64.zip
+```
+Before running the script, make sure the artifacts are accessible from:
+http://repo1.maven.org/maven2/com/google/protobuf/protoc/
+
### Tips for deploying on Linux
We build on Centos 6.6 to provide a good compatibility for not very new
systems. We have provided a ``Dockerfile`` under this directory to build the
diff --git a/protoc-artifacts/build-protoc.sh b/protoc-artifacts/build-protoc.sh
index 88e6ae50..e31948e9 100755
--- a/protoc-artifacts/build-protoc.sh
+++ b/protoc-artifacts/build-protoc.sh
@@ -1,17 +1,30 @@
#!/bin/bash
-# Builds protoc executable into target/protoc.exe
+# Builds protoc executable into target/protoc.exe; optionally build protoc
+# plugins into target/protoc-gen-*.exe
# To be run from Maven.
-# Usage: build-protoc.sh <OS> <ARCH>
+# Usage: build-protoc.sh <OS> <ARCH> <TARGET>
# <OS> and <ARCH> are ${os.detected.name} and ${os.detected.arch} from os-maven-plugin
+# <TARGET> can be "protoc" or "protoc-gen-javalite"
OS=$1
ARCH=$2
+MAKE_TARGET=$3
-if [[ $# < 2 ]]; then
+if [[ $# < 3 ]]; then
echo "No arguments provided. This script is intended to be run from Maven."
exit 1
fi
+case $MAKE_TARGET in
+ protoc-gen-javalite)
+ ;;
+ protoc)
+ ;;
+ *)
+ echo "Target ""$TARGET"" invalid."
+ exit 1
+esac
+
# Under Cygwin, bash doesn't have these in PATH when called from Maven which
# runs in Windows version of Java.
export PATH="/bin:/usr/bin:$PATH"
@@ -126,7 +139,7 @@ checkDependencies ()
}
############################################################################
-echo "Building protoc, OS=$OS ARCH=$ARCH"
+echo "Building protoc, OS=$OS ARCH=$ARCH TARGET=$TARGET"
# Nested double quotes are unintuitive, but it works.
cd "$(dirname "$0")"
@@ -134,7 +147,7 @@ cd "$(dirname "$0")"
WORKING_DIR=$(pwd)
CONFIGURE_ARGS="--disable-shared"
-MAKE_TARGET="protoc"
+TARGET_FILE=target/$MAKE_TARGET.exe
if [[ "$OS" == windows ]]; then
MAKE_TARGET="${MAKE_TARGET}.exe"
fi
@@ -209,12 +222,10 @@ fi
export CXXFLAGS LDFLAGS
-TARGET_FILE=target/protoc.exe
-
cd "$WORKING_DIR"/.. && ./configure $CONFIGURE_ARGS &&
cd src && make clean && make $MAKE_TARGET &&
cd "$WORKING_DIR" && mkdir -p target &&
- (cp ../src/protoc $TARGET_FILE || cp ../src/protoc.exe $TARGET_FILE) ||
+ cp ../src/$MAKE_TARGET $TARGET_FILE ||
exit 1
if [[ "$OS" == osx ]]; then
diff --git a/protoc-artifacts/build-zip.sh b/protoc-artifacts/build-zip.sh
new file mode 100755
index 00000000..3c5e887b
--- /dev/null
+++ b/protoc-artifacts/build-zip.sh
@@ -0,0 +1,108 @@
+#!/bin/bash
+
+if [ $# -ne 2 ]; then
+ cat <<EOF
+Usage: $0 <TARGET> <VERSION_NUMBER>
+
+TARGET: protoc | protoc-gen-javalite
+
+Example:
+ $ $0 protoc 3.0.0
+ $ $0 protoc-gen-javalite 3.0.0
+
+This script will download pre-built protoc or protoc plugin binaries from maven
+repository and create .zip packages suitable to be included in the github
+release page. If the target is protoc, well-known type .proto files will also be
+included. Each invocation will create 5 zip packages:
+ dist/<TARGET>-<VERSION_NUMBER>-win32.zip
+ dist/<TARGET>-<VERSION_NUMBER>-osx-x86_32.zip
+ dist/<TARGET>-<VERSION_NUMBER>-osx-x86_64.zip
+ dist/<TARGET>-<VERSION_NUMBER>-linux-x86_32.zip
+ dist/<TARGET>-<VERSION_NUMBER>-linux-x86_64.zip
+EOF
+ exit 1
+fi
+
+TARGET=$1
+VERSION_NUMBER=$2
+
+# <zip file name> <binary file name> pairs.
+declare -a FILE_NAMES=( \
+ win32.zip windows-x86_32.exe \
+ osx-x86_32.zip osx-x86_32.exe \
+ osx-x86_64.zip osx-x86_64.exe \
+ linux-x86_32.zip linux-x86_32.exe \
+ linux-x86_64.zip linux-x86_64.exe \
+)
+
+# List of all well-known types to be included.
+declare -a WELL_KNOWN_TYPES=( \
+ google/protobuf/descriptor.proto \
+ google/protobuf/any.proto \
+ google/protobuf/api.proto \
+ google/protobuf/duration.proto \
+ google/protobuf/empty.proto \
+ google/protobuf/field_mask.proto \
+ google/protobuf/source_context.proto \
+ google/protobuf/struct.proto \
+ google/protobuf/timestamp.proto \
+ google/protobuf/type.proto \
+ google/protobuf/wrappers.proto \
+ google/protobuf/compiler/plugin.proto \
+)
+
+set -e
+
+# A temporary working directory to put all files.
+DIR=$(mktemp -d)
+
+# Copy over well-known types.
+mkdir -p ${DIR}/include/google/protobuf/compiler
+for PROTO in ${WELL_KNOWN_TYPES[@]}; do
+ cp -f ../src/${PROTO} ${DIR}/include/${PROTO}
+done
+
+# Create a readme file.
+cat <<EOF > ${DIR}/readme.txt
+Protocol Buffers - Google's data interchange format
+Copyright 2008 Google Inc.
+https://developers.google.com/protocol-buffers/
+
+This package contains a precompiled binary version of the protocol buffer
+compiler (protoc). This binary is intended for users who want to use Protocol
+Buffers in languages other than C++ but do not want to compile protoc
+themselves. To install, simply place this binary somewhere in your PATH.
+
+Please refer to our official github site for more installation instructions:
+ https://github.com/google/protobuf
+EOF
+
+mkdir -p dist
+mkdir -p ${DIR}/bin
+# Create a zip file for each binary.
+for((i=0;i<${#FILE_NAMES[@]};i+=2));do
+ ZIP_NAME=${FILE_NAMES[$i]}
+ if [ ${ZIP_NAME:0:3} = "win" ]; then
+ BINARY="$TARGET.exe"
+ else
+ BINARY="$TARGET"
+ fi
+ BINARY_NAME=${FILE_NAMES[$(($i+1))]}
+ BINARY_URL=http://repo1.maven.org/maven2/com/google/protobuf/$TARGET/${VERSION_NUMBER}/$TARGET-${VERSION_NUMBER}-${BINARY_NAME}
+ if ! wget ${BINARY_URL} -O ${DIR}/bin/$BINARY &> /dev/null; then
+ echo "[ERROR] Failed to download ${BINARY_URL}" >&2
+ echo "[ERROR] Skipped $TARGET-${VERSION_NAME}-${ZIP_NAME}" >&2
+ continue
+ fi
+ TARGET_ZIP_FILE=`pwd`/dist/$TARGET-${VERSION_NUMBER}-${ZIP_NAME}
+ pushd $DIR &> /dev/null
+ chmod +x bin/$BINARY
+ if [ "$TARGET" = "protoc" ]; then
+ zip -r ${TARGET_ZIP_FILE} include bin readme.txt &> /dev/null
+ else
+ zip -r ${TARGET_ZIP_FILE} bin &> /dev/null
+ fi
+ rm bin/$BINARY
+ popd &> /dev/null
+ echo "[INFO] Successfully created ${TARGET_ZIP_FILE}"
+done
diff --git a/protoc-artifacts/pom.xml b/protoc-artifacts/pom.xml
index 50866041..840bc60a 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-beta-3</version>
+ <version>3.0.0</version>
<packaging>pom</packaging>
<name>Protobuf Compiler</name>
<description>
@@ -59,6 +59,7 @@
<argument>build-protoc.sh</argument>
<argument>${os.detected.name}</argument>
<argument>${os.detected.arch}</argument>
+ <argument>protoc</argument>
</arguments>
</configuration>
</plugin>
diff --git a/python/google/protobuf/__init__.py b/python/google/protobuf/__init__.py
index 2a3c6771..6210a404 100755
--- a/python/google/protobuf/__init__.py
+++ b/python/google/protobuf/__init__.py
@@ -30,7 +30,7 @@
# Copyright 2007 Google Inc. All Rights Reserved.
-__version__ = '3.0.0b3'
+__version__ = '3.0.0'
if __name__ != '__main__':
try:
diff --git a/python/google/protobuf/internal/json_format_test.py b/python/google/protobuf/internal/json_format_test.py
index 6df12bea..a5ee8ace 100644
--- a/python/google/protobuf/internal/json_format_test.py
+++ b/python/google/protobuf/internal/json_format_test.py
@@ -252,10 +252,7 @@ class JsonFormatTest(JsonFormatBase):
message = json_format_proto3_pb2.TestMessage()
json_format.Parse('{"stringValue": "\\uD83D\\uDE01"}', message)
self.assertEqual(message.string_value,
- b'\xF0\x9F\x98\x81'.decode("utf-8", "strict"))
-
- # TODO: add test that UTF-8 encoded surrogate code points are rejected.
- # UTF-8 does not allow them.
+ b'\xF0\x9F\x98\x81'.decode('utf-8', 'strict'))
# Error case: unpaired high surrogate.
self.CheckError(
@@ -267,7 +264,6 @@ class JsonFormatTest(JsonFormatBase):
'{"stringValue": "\\uDE01"}',
r'Invalid \\uXXXX escape|Unpaired.*surrogate')
-
def testTimestampMessage(self):
message = json_format_proto3_pb2.TestTimestamp()
message.value.seconds = 0
diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py
index f8f73dd2..c0d0ad45 100755
--- a/python/google/protobuf/internal/python_message.py
+++ b/python/google/protobuf/internal/python_message.py
@@ -76,7 +76,6 @@ from google.protobuf.internal import well_known_types
from google.protobuf.internal import wire_format
from google.protobuf import descriptor as descriptor_mod
from google.protobuf import message as message_mod
-from google.protobuf import symbol_database
from google.protobuf import text_format
_FieldDescriptor = descriptor_mod.FieldDescriptor
@@ -98,16 +97,12 @@ class GeneratedProtocolMessageType(type):
classes at runtime, as in this example:
mydescriptor = Descriptor(.....)
- class MyProtoClass(Message):
- __metaclass__ = GeneratedProtocolMessageType
- DESCRIPTOR = mydescriptor
+ factory = symbol_database.Default()
+ factory.pool.AddDescriptor(mydescriptor)
+ MyProtoClass = factory.GetPrototype(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
@@ -926,26 +921,33 @@ def _InternalUnpackAny(msg):
Returns:
The unpacked message.
"""
+ # TODO(amauryfa): Don't use the factory of generated messages.
+ # To make Any work with custom factories, use the message factory of the
+ # parent message.
+ # pylint: disable=g-import-not-at-top
+ from google.protobuf import symbol_database
+ factory = symbol_database.Default()
+
type_url = msg.type_url
- db = symbol_database.Default()
if not type_url:
return None
# TODO(haberman): For now we just strip the hostname. Better logic will be
# required.
- type_name = type_url.split("/")[-1]
- descriptor = db.pool.FindMessageTypeByName(type_name)
+ type_name = type_url.split('/')[-1]
+ descriptor = factory.pool.FindMessageTypeByName(type_name)
if descriptor is None:
return None
- message_class = db.GetPrototype(descriptor)
+ message_class = factory.GetPrototype(descriptor)
message = message_class()
message.ParseFromString(msg.value)
return message
+
def _AddEqualsMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
def __eq__(self, other):
diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index 6dc2fffe..6f3b818a 100755
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -636,7 +636,7 @@ class ReflectionTest(unittest.TestCase):
if struct.calcsize('L') == 4:
# Python only has signed ints, so 32-bit python can't fit an uint32
# in an int.
- TestGetAndDeserialize('optional_uint32', 1 << 31, long)
+ TestGetAndDeserialize('optional_uint32', 1 << 31, integer_64)
else:
# 64-bit python can fit uint32 inside an int
TestGetAndDeserialize('optional_uint32', 1 << 31, int)
@@ -972,6 +972,7 @@ class ReflectionTest(unittest.TestCase):
proto.repeated_nested_message.add(bb=23)
self.assertEqual(1, len(proto.repeated_nested_message))
self.assertEqual(23, proto.repeated_nested_message[0].bb)
+ self.assertRaises(TypeError, proto.repeated_nested_message.add, 23)
def testRepeatedCompositeRemove(self):
proto = unittest_pb2.TestAllTypes()
diff --git a/python/google/protobuf/internal/symbol_database_test.py b/python/google/protobuf/internal/symbol_database_test.py
index c99b426d..4f5173b2 100644
--- a/python/google/protobuf/internal/symbol_database_test.py
+++ b/python/google/protobuf/internal/symbol_database_test.py
@@ -39,26 +39,28 @@ except ImportError:
from google.protobuf import unittest_pb2
from google.protobuf import descriptor
+from google.protobuf import descriptor_pool
from google.protobuf import symbol_database
+
class SymbolDatabaseTest(unittest.TestCase):
def _Database(self):
- # TODO(b/17734095): Remove this difference when the C++ implementation
- # supports multiple databases.
if descriptor._USE_C_DESCRIPTORS:
- return symbol_database.Default()
+ # The C++ implementation does not allow mixing descriptors from
+ # different pools.
+ db = symbol_database.SymbolDatabase(pool=descriptor_pool.Default())
else:
db = symbol_database.SymbolDatabase()
- # Register representative types from unittest_pb2.
- db.RegisterFileDescriptor(unittest_pb2.DESCRIPTOR)
- db.RegisterMessage(unittest_pb2.TestAllTypes)
- db.RegisterMessage(unittest_pb2.TestAllTypes.NestedMessage)
- db.RegisterMessage(unittest_pb2.TestAllTypes.OptionalGroup)
- db.RegisterMessage(unittest_pb2.TestAllTypes.RepeatedGroup)
- db.RegisterEnumDescriptor(unittest_pb2.ForeignEnum.DESCRIPTOR)
- db.RegisterEnumDescriptor(unittest_pb2.TestAllTypes.NestedEnum.DESCRIPTOR)
- return db
+ # Register representative types from unittest_pb2.
+ db.RegisterFileDescriptor(unittest_pb2.DESCRIPTOR)
+ db.RegisterMessage(unittest_pb2.TestAllTypes)
+ db.RegisterMessage(unittest_pb2.TestAllTypes.NestedMessage)
+ db.RegisterMessage(unittest_pb2.TestAllTypes.OptionalGroup)
+ db.RegisterMessage(unittest_pb2.TestAllTypes.RepeatedGroup)
+ db.RegisterEnumDescriptor(unittest_pb2.ForeignEnum.DESCRIPTOR)
+ db.RegisterEnumDescriptor(unittest_pb2.TestAllTypes.NestedEnum.DESCRIPTOR)
+ return db
def testGetPrototype(self):
instance = self._Database().GetPrototype(
diff --git a/python/google/protobuf/json_format.py b/python/google/protobuf/json_format.py
index bb6a1998..edc0cb50 100644
--- a/python/google/protobuf/json_format.py
+++ b/python/google/protobuf/json_format.py
@@ -310,7 +310,7 @@ def Parse(text, message, ignore_unknown_fields=False):
Args:
text: Message JSON representation.
- message: A protocol beffer message to merge into.
+ message: A protocol buffer message to merge into.
ignore_unknown_fields: If True, do not raise errors for unknown fields.
Returns:
diff --git a/python/google/protobuf/pyext/cpp_message.py b/python/google/protobuf/pyext/cpp_message.py
index b215211e..fc8eb32d 100644
--- a/python/google/protobuf/pyext/cpp_message.py
+++ b/python/google/protobuf/pyext/cpp_message.py
@@ -48,9 +48,9 @@ class GeneratedProtocolMessageType(_message.MessageMeta):
classes at runtime, as in this example:
mydescriptor = Descriptor(.....)
- class MyProtoClass(Message):
- __metaclass__ = GeneratedProtocolMessageType
- DESCRIPTOR = mydescriptor
+ factory = symbol_database.Default()
+ factory.pool.AddDescriptor(mydescriptor)
+ MyProtoClass = factory.GetPrototype(mydescriptor)
myproto_instance = MyProtoClass()
myproto.foo_field = 23
...
diff --git a/python/google/protobuf/pyext/map_container.cc b/python/google/protobuf/pyext/map_container.cc
index 90438df1..0987b898 100644
--- a/python/google/protobuf/pyext/map_container.cc
+++ b/python/google/protobuf/pyext/map_container.cc
@@ -348,9 +348,10 @@ PyObject* MapReflectionFriend::Contains(PyObject* _self, PyObject* key) {
}
// Initializes the underlying Message object of "to" so it becomes a new parent
-// repeated scalar, and copies all the values from "from" to it. A child scalar
+// map container, and copies all the values from "from" to it. A child map
// container can be released by passing it as both from and to (e.g. making it
// the recipient of the new parent message and copying the values from itself).
+// In fact, this is the only supported use at the moment.
static int InitializeAndCopyToParentContainer(MapContainer* from,
MapContainer* to) {
// For now we require from == to, re-evaluate if we want to support deep copy
diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc
index a9261f20..5535338d 100644
--- a/python/google/protobuf/pyext/message.cc
+++ b/python/google/protobuf/pyext/message.cc
@@ -1041,7 +1041,12 @@ int InternalDeleteRepeatedField(
}
// Initializes fields of a message. Used in constructors.
-int InitAttributes(CMessage* self, PyObject* kwargs) {
+int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) {
+ if (args != NULL && PyTuple_Size(args) != 0) {
+ PyErr_SetString(PyExc_TypeError, "No positional arguments allowed");
+ return -1;
+ }
+
if (kwargs == NULL) {
return 0;
}
@@ -1167,7 +1172,7 @@ int InitAttributes(CMessage* self, PyObject* kwargs) {
}
CMessage* cmessage = reinterpret_cast<CMessage*>(message.get());
if (PyDict_Check(value)) {
- if (InitAttributes(cmessage, value) < 0) {
+ if (InitAttributes(cmessage, NULL, value) < 0) {
return -1;
}
} else {
@@ -1245,12 +1250,7 @@ static PyObject* New(PyTypeObject* cls,
// The __init__ method of Message classes.
// It initializes fields from keywords passed to the constructor.
static int Init(CMessage* self, PyObject* args, PyObject* kwargs) {
- if (PyTuple_Size(args) != 0) {
- PyErr_SetString(PyExc_TypeError, "No positional arguments allowed");
- return -1;
- }
-
- return InitAttributes(self, kwargs);
+ return InitAttributes(self, args, kwargs);
}
// ---------------------------------------------------------------------
diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h
index 8b399e05..c44a2ae2 100644
--- a/python/google/protobuf/pyext/message.h
+++ b/python/google/protobuf/pyext/message.h
@@ -237,7 +237,9 @@ PyObject* HasFieldByDescriptor(
PyObject* HasField(CMessage* self, PyObject* arg);
// Initializes values of fields on a newly constructed message.
-int InitAttributes(CMessage* self, PyObject* kwargs);
+// Note that positional arguments are disallowed: 'args' must be NULL or the
+// empty tuple.
+int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs);
PyObject* MergeFrom(CMessage* self, PyObject* arg);
diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc
index 4f339e77..bb2f6db2 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.cc
+++ b/python/google/protobuf/pyext/repeated_composite_container.cc
@@ -146,7 +146,7 @@ static PyObject* AddToAttached(RepeatedCompositeContainer* self,
cmsg->owner = self->owner;
cmsg->message = sub_message;
cmsg->parent = self->parent;
- if (cmessage::InitAttributes(cmsg, kwargs) < 0) {
+ if (cmessage::InitAttributes(cmsg, args, kwargs) < 0) {
Py_DECREF(cmsg);
return NULL;
}
@@ -166,7 +166,7 @@ static PyObject* AddToReleased(RepeatedCompositeContainer* self,
// Create a new Message detached from the rest.
PyObject* py_cmsg = PyEval_CallObjectWithKeywords(
- self->child_message_class->AsPyObject(), NULL, kwargs);
+ self->child_message_class->AsPyObject(), args, kwargs);
if (py_cmsg == NULL)
return NULL;
diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py
index 0c757264..51c83321 100755
--- a/python/google/protobuf/reflection.py
+++ b/python/google/protobuf/reflection.py
@@ -58,13 +58,7 @@ else:
from google.protobuf.internal import python_message as message_impl
# 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
+# Part of the public interface, but normally only used by message factories.
GeneratedProtocolMessageType = message_impl.GeneratedProtocolMessageType
diff --git a/python/google/protobuf/symbol_database.py b/python/google/protobuf/symbol_database.py
index 87760f26..aa466abd 100644
--- a/python/google/protobuf/symbol_database.py
+++ b/python/google/protobuf/symbol_database.py
@@ -30,11 +30,9 @@
"""A database of Python protocol buffer generated symbols.
-SymbolDatabase makes it easy to create new instances of a registered type, given
-only the type's protocol buffer symbol name. Once all symbols are registered,
-they can be accessed using either the MessageFactory interface which
-SymbolDatabase exposes, or the DescriptorPool interface of the underlying
-pool.
+SymbolDatabase is the MessageFactory for messages generated at compile time,
+and makes it easy to create new instances of a registered type, given only the
+type's protocol buffer symbol name.
Example usage:
@@ -61,27 +59,17 @@ Example usage:
from google.protobuf import descriptor_pool
+from google.protobuf import message_factory
-class SymbolDatabase(object):
- """A database of Python generated symbols.
-
- SymbolDatabase also models message_factory.MessageFactory.
-
- The symbol database can be used to keep a global registry of all protocol
- buffer types used within a program.
- """
-
- def __init__(self, pool=None):
- """Constructor."""
-
- self._symbols = {}
- self._symbols_by_file = {}
- self.pool = pool or descriptor_pool.Default()
+class SymbolDatabase(message_factory.MessageFactory):
+ """A database of Python generated symbols."""
def RegisterMessage(self, message):
"""Registers the given message type in the local database.
+ Calls to GetSymbol() and GetMessages() will return messages registered here.
+
Args:
message: a message.Message, to be registered.
@@ -90,10 +78,7 @@ class SymbolDatabase(object):
"""
desc = message.DESCRIPTOR
- self._symbols[desc.full_name] = message
- if desc.file.name not in self._symbols_by_file:
- self._symbols_by_file[desc.file.name] = {}
- self._symbols_by_file[desc.file.name][desc.full_name] = message
+ self._classes[desc.full_name] = message
self.pool.AddDescriptor(desc)
return message
@@ -136,47 +121,46 @@ class SymbolDatabase(object):
KeyError: if the symbol could not be found.
"""
- return self._symbols[symbol]
-
- def GetPrototype(self, descriptor):
- """Builds a proto2 message class based on the passed in descriptor.
-
- Passing a descriptor with a fully qualified name matching a previous
- invocation will cause the same class to be returned.
-
- Args:
- descriptor: The descriptor to build from.
-
- Returns:
- A class describing the passed in descriptor.
- """
-
- return self.GetSymbol(descriptor.full_name)
+ return self._classes[symbol]
def GetMessages(self, files):
- """Gets all the messages from a specified file.
-
- This will find and resolve dependencies, failing if they are not registered
- in the symbol database.
+ # TODO(amauryfa): Fix the differences with MessageFactory.
+ """Gets all registered messages from a specified file.
+ Only messages already created and registered will be returned; (this is the
+ case for imported _pb2 modules)
+ But unlike MessageFactory, this version also returns nested messages.
Args:
files: The file names to extract messages from.
Returns:
- A dictionary mapping proto names to the message classes. This will include
- any dependent messages as well as any messages defined in the same file as
- a specified message.
+ A dictionary mapping proto names to the message classes.
Raises:
KeyError: if a file could not be found.
"""
+ def _GetAllMessageNames(desc):
+ """Walk a message Descriptor and recursively yields all message names."""
+ yield desc.full_name
+ for msg_desc in desc.nested_types:
+ for full_name in _GetAllMessageNames(msg_desc):
+ yield full_name
+
result = {}
- for f in files:
- result.update(self._symbols_by_file[f])
+ for file_name in files:
+ file_desc = self.pool.FindFileByName(file_name)
+ for msg_desc in file_desc.message_types_by_name.values():
+ for full_name in _GetAllMessageNames(msg_desc):
+ try:
+ result[full_name] = self._classes[full_name]
+ except KeyError:
+ # This descriptor has no registered class, skip it.
+ pass
return result
+
_DEFAULT = SymbolDatabase(pool=descriptor_pool.Default())
diff --git a/python/setup.cfg b/python/setup.cfg
new file mode 100644
index 00000000..2a9acf13
--- /dev/null
+++ b/python/setup.cfg
@@ -0,0 +1,2 @@
+[bdist_wheel]
+universal = 1
diff --git a/ruby/Rakefile b/ruby/Rakefile
index fa29c315..ba1cf4cf 100644
--- a/ruby/Rakefile
+++ b/ruby/Rakefile
@@ -31,7 +31,7 @@ genproto_output = []
unless ENV['IN_DOCKER'] == 'true'
well_known_protos.each do |proto_file|
input_file = "../src/" + proto_file
- output_file = "lib/" + proto_file.sub(/\.proto$/, ".rb")
+ output_file = "lib/" + proto_file.sub(/\.proto$/, "_pb.rb")
genproto_output << output_file
file output_file => input_file do |file_task|
sh "../src/protoc -I../src --ruby_out=lib #{input_file}"
@@ -80,10 +80,15 @@ end
# Proto for tests.
genproto_output << "tests/generated_code.rb"
+genproto_output << "tests/test_import.rb"
file "tests/generated_code.rb" => "tests/generated_code.proto" do |file_task|
sh "../src/protoc --ruby_out=. tests/generated_code.proto"
end
+file "tests/test_import.rb" => "tests/test_import.proto" do |file_task|
+ sh "../src/protoc --ruby_out=. tests/test_import.proto"
+end
+
task :genproto => genproto_output
task :clean do
diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c
index f6bea50f..08c72bcc 100644
--- a/ruby/ext/google/protobuf_c/encode_decode.c
+++ b/ruby/ext/google/protobuf_c/encode_decode.c
@@ -54,7 +54,7 @@ VALUE noleak_rb_str_cat(VALUE rb_str, const char *str, long len) {
static const void* newhandlerdata(upb_handlers* h, uint32_t ofs) {
size_t* hd_ofs = ALLOC(size_t);
*hd_ofs = ofs;
- upb_handlers_addcleanup(h, hd_ofs, free);
+ upb_handlers_addcleanup(h, hd_ofs, xfree);
return hd_ofs;
}
@@ -69,7 +69,7 @@ static const void *newsubmsghandlerdata(upb_handlers* h, uint32_t ofs,
submsg_handlerdata_t *hd = ALLOC(submsg_handlerdata_t);
hd->ofs = ofs;
hd->md = upb_fielddef_msgsubdef(f);
- upb_handlers_addcleanup(h, hd, free);
+ upb_handlers_addcleanup(h, hd, xfree);
return hd;
}
@@ -99,7 +99,7 @@ static const void *newoneofhandlerdata(upb_handlers *h,
} else {
hd->md = NULL;
}
- upb_handlers_addcleanup(h, hd, free);
+ upb_handlers_addcleanup(h, hd, xfree);
return hd;
}
@@ -135,7 +135,7 @@ static void* appendstr_handler(void *closure,
VALUE ary = (VALUE)closure;
VALUE str = rb_str_new2("");
rb_enc_associate(str, kRubyStringUtf8Encoding);
- RepeatedField_push(ary, str);
+ RepeatedField_push_native(ary, &str);
return (void*)str;
}
@@ -146,7 +146,7 @@ static void* appendbytes_handler(void *closure,
VALUE ary = (VALUE)closure;
VALUE str = rb_str_new2("");
rb_enc_associate(str, kRubyString8bitEncoding);
- RepeatedField_push(ary, str);
+ RepeatedField_push_native(ary, &str);
return (void*)str;
}
@@ -182,6 +182,23 @@ static size_t stringdata_handler(void* closure, const void* hd,
return len;
}
+static bool stringdata_end_handler(void* closure, const void* hd) {
+ MessageHeader* msg = closure;
+ const size_t *ofs = hd;
+ VALUE rb_str = DEREF(msg, *ofs, VALUE);
+ rb_obj_freeze(rb_str);
+ return true;
+}
+
+static bool appendstring_end_handler(void* closure, const void* hd) {
+ VALUE ary = (VALUE)closure;
+ int size = RepeatedField_size(ary);
+ VALUE* last = RepeatedField_index_native(ary, size - 1);
+ VALUE rb_str = *last;
+ rb_obj_freeze(rb_str);
+ return true;
+}
+
// Appends a submessage to a repeated field (a regular Ruby array for now).
static void *appendsubmsg_handler(void *closure, const void *hd) {
VALUE ary = (VALUE)closure;
@@ -238,10 +255,54 @@ typedef struct {
// value into the map.
typedef struct {
VALUE map;
+ const map_handlerdata_t* handlerdata;
char key_storage[NATIVE_SLOT_MAX_SIZE];
char value_storage[NATIVE_SLOT_MAX_SIZE];
} map_parse_frame_t;
+static void MapParseFrame_mark(void* _self) {
+ map_parse_frame_t* frame = _self;
+
+ // This shouldn't strictly be necessary since this should be rooted by the
+ // message itself, but it can't hurt.
+ rb_gc_mark(frame->map);
+
+ native_slot_mark(frame->handlerdata->key_field_type, &frame->key_storage);
+ native_slot_mark(frame->handlerdata->value_field_type, &frame->value_storage);
+}
+
+void MapParseFrame_free(void* self) {
+ xfree(self);
+}
+
+rb_data_type_t MapParseFrame_type = {
+ "MapParseFrame",
+ { MapParseFrame_mark, MapParseFrame_free, NULL },
+};
+
+// Array of Ruby objects wrapping map_parse_frame_t.
+// We don't allow multiple concurrent decodes, so we assume that this global
+// variable is specific to the "current" decode.
+VALUE map_parse_frames;
+
+static map_parse_frame_t* map_push_frame(VALUE map,
+ const map_handlerdata_t* handlerdata) {
+ map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
+ frame->handlerdata = handlerdata;
+ frame->map = map;
+ native_slot_init(handlerdata->key_field_type, &frame->key_storage);
+ native_slot_init(handlerdata->value_field_type, &frame->value_storage);
+
+ rb_ary_push(map_parse_frames,
+ TypedData_Wrap_Struct(rb_cObject, &MapParseFrame_type, frame));
+
+ return frame;
+}
+
+static void map_pop_frame() {
+ rb_ary_pop(map_parse_frames);
+}
+
// Handler to begin a map entry: allocates a temporary frame. This is the
// 'startsubmsg' handler on the msgdef that contains the map field.
static void *startmapentry_handler(void *closure, const void *hd) {
@@ -249,13 +310,7 @@ static void *startmapentry_handler(void *closure, const void *hd) {
const map_handlerdata_t* mapdata = hd;
VALUE map_rb = DEREF(msg, mapdata->ofs, VALUE);
- map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
- frame->map = map_rb;
-
- native_slot_init(mapdata->key_field_type, &frame->key_storage);
- native_slot_init(mapdata->value_field_type, &frame->value_storage);
-
- return frame;
+ return map_push_frame(map_rb, mapdata);
}
// Handler to end a map entry: inserts the value defined during the message into
@@ -281,7 +336,7 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) {
&frame->value_storage);
Map_index_set(frame->map, key, value);
- free(frame);
+ map_pop_frame();
return true;
}
@@ -360,6 +415,13 @@ static void *oneofbytes_handler(void *closure,
return (void*)str;
}
+static bool oneofstring_end_handler(void* closure, const void* hd) {
+ MessageHeader* msg = closure;
+ const oneof_handlerdata_t *oneofdata = hd;
+ rb_obj_freeze(DEREF(msg, oneofdata->ofs, VALUE));
+ return true;
+}
+
// Handler for a submessage field in a oneof.
static void *oneofsubmsg_handler(void *closure,
const void *hd) {
@@ -426,6 +488,7 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
appendbytes_handler : appendstr_handler,
NULL);
upb_handlers_setstring(h, f, stringdata_handler, NULL);
+ upb_handlers_setendstr(h, f, appendstring_end_handler, NULL);
break;
}
case UPB_TYPE_MESSAGE: {
@@ -462,6 +525,7 @@ static void add_handlers_for_singular_field(upb_handlers *h,
is_bytes ? bytes_handler : str_handler,
&attr);
upb_handlers_setstring(h, f, stringdata_handler, &attr);
+ upb_handlers_setendstr(h, f, stringdata_end_handler, &attr);
upb_handlerattr_uninit(&attr);
break;
}
@@ -484,7 +548,7 @@ static void add_handlers_for_mapfield(upb_handlers* h,
map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc);
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
- upb_handlers_addcleanup(h, hd, free);
+ upb_handlers_addcleanup(h, hd, xfree);
upb_handlerattr_sethandlerdata(&attr, hd);
upb_handlers_setstartsubmsg(h, fielddef, startmapentry_handler, &attr);
upb_handlerattr_uninit(&attr);
@@ -499,7 +563,7 @@ static void add_handlers_for_mapentry(const upb_msgdef* msgdef,
map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc);
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
- upb_handlers_addcleanup(h, hd, free);
+ upb_handlers_addcleanup(h, hd, xfree);
upb_handlerattr_sethandlerdata(&attr, hd);
upb_handlers_setendmsg(h, endmap_handler, &attr);
@@ -546,6 +610,7 @@ static void add_handlers_for_oneof_field(upb_handlers *h,
oneofbytes_handler : oneofstr_handler,
&attr);
upb_handlers_setstring(h, f, stringdata_handler, NULL);
+ upb_handlers_setendstr(h, f, oneofstring_end_handler, &attr);
break;
}
case UPB_TYPE_MESSAGE: {
@@ -710,6 +775,10 @@ VALUE Message_decode(VALUE klass, VALUE data) {
msg_rb = rb_class_new_instance(0, NULL, msgklass);
TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
+ // We generally expect this to be clear already, but clear it in case parsing
+ // previously got interrupted somehow.
+ rb_ary_clear(map_parse_frames);
+
{
const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
@@ -754,6 +823,10 @@ VALUE Message_decode_json(VALUE klass, VALUE data) {
msg_rb = rb_class_new_instance(0, NULL, msgklass);
TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
+ // We generally expect this to be clear already, but clear it in case parsing
+ // previously got interrupted somehow.
+ rb_ary_clear(map_parse_frames);
+
{
const upb_json_parsermethod* method = msgdef_jsonparsermethod(desc);
stackenv se;
@@ -863,9 +936,13 @@ static void putstr(VALUE str, const upb_fielddef *f, upb_sink *sink) {
assert(BUILTIN_TYPE(str) == RUBY_T_STRING);
- // Ensure that the string has the correct encoding. We also check at field-set
- // time, but the user may have mutated the string object since then.
- native_slot_validate_string_encoding(upb_fielddef_type(f), str);
+ // We should be guaranteed that the string has the correct encoding because
+ // we ensured this at assignment time and then froze the string.
+ if (upb_fielddef_type(f) == UPB_TYPE_STRING) {
+ assert(rb_enc_from_index(ENCODING_GET(value)) == kRubyStringUtf8Encoding);
+ } else {
+ assert(rb_enc_from_index(ENCODING_GET(value)) == kRubyString8bitEncoding);
+ }
upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), RSTRING_LEN(str),
&subsink);
diff --git a/ruby/ext/google/protobuf_c/map.c b/ruby/ext/google/protobuf_c/map.c
index 92fc7286..12f1f9dd 100644
--- a/ruby/ext/google/protobuf_c/map.c
+++ b/ruby/ext/google/protobuf_c/map.c
@@ -63,16 +63,16 @@
// construct a key byte sequence if needed. |out_key| and |out_length| provide
// the resulting key data/length.
#define TABLE_KEY_BUF_LENGTH 8 // sizeof(uint64_t)
-static void table_key(Map* self, VALUE key,
- char* buf,
- const char** out_key,
- size_t* out_length) {
+static VALUE table_key(Map* self, VALUE key,
+ char* buf,
+ const char** out_key,
+ size_t* out_length) {
switch (self->key_type) {
case UPB_TYPE_BYTES:
case UPB_TYPE_STRING:
// Strings: use string content directly.
Check_Type(key, T_STRING);
- native_slot_validate_string_encoding(self->key_type, key);
+ key = native_slot_encode_and_freeze_string(self->key_type, key);
*out_key = RSTRING_PTR(key);
*out_length = RSTRING_LEN(key);
break;
@@ -93,6 +93,8 @@ static void table_key(Map* self, VALUE key,
assert(false);
break;
}
+
+ return key;
}
static VALUE table_key_to_ruby(Map* self, const char* buf, size_t length) {
@@ -357,7 +359,7 @@ VALUE Map_index(VALUE _self, VALUE key) {
const char* keyval = NULL;
size_t length = 0;
upb_value v;
- table_key(self, key, keybuf, &keyval, &length);
+ key = table_key(self, key, keybuf, &keyval, &length);
if (upb_strtable_lookup2(&self->table, keyval, length, &v)) {
void* mem = value_memory(&v);
@@ -383,7 +385,7 @@ VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) {
size_t length = 0;
upb_value v;
void* mem;
- table_key(self, key, keybuf, &keyval, &length);
+ key = table_key(self, key, keybuf, &keyval, &length);
mem = value_memory(&v);
native_slot_set(self->value_type, self->value_type_class, mem, value);
@@ -411,7 +413,7 @@ VALUE Map_has_key(VALUE _self, VALUE key) {
char keybuf[TABLE_KEY_BUF_LENGTH];
const char* keyval = NULL;
size_t length = 0;
- table_key(self, key, keybuf, &keyval, &length);
+ key = table_key(self, key, keybuf, &keyval, &length);
if (upb_strtable_lookup2(&self->table, keyval, length, NULL)) {
return Qtrue;
@@ -434,7 +436,7 @@ VALUE Map_delete(VALUE _self, VALUE key) {
const char* keyval = NULL;
size_t length = 0;
upb_value v;
- table_key(self, key, keybuf, &keyval, &length);
+ key = table_key(self, key, keybuf, &keyval, &length);
if (upb_strtable_remove2(&self->table, keyval, length, &v)) {
void* mem = value_memory(&v);
diff --git a/ruby/ext/google/protobuf_c/protobuf.c b/ruby/ext/google/protobuf_c/protobuf.c
index 7cde4aec..98963667 100644
--- a/ruby/ext/google/protobuf_c/protobuf.c
+++ b/ruby/ext/google/protobuf_c/protobuf.c
@@ -112,4 +112,6 @@ void Init_protobuf_c() {
upb_def_to_ruby_obj_map = rb_hash_new();
rb_gc_register_address(&upb_def_to_ruby_obj_map);
+ map_parse_frames = rb_ary_new();
+ rb_gc_register_address(&map_parse_frames);
}
diff --git a/ruby/ext/google/protobuf_c/protobuf.h b/ruby/ext/google/protobuf_c/protobuf.h
index 2834c894..d5ced567 100644
--- a/ruby/ext/google/protobuf_c/protobuf.h
+++ b/ruby/ext/google/protobuf_c/protobuf.h
@@ -166,6 +166,8 @@ extern VALUE cBuilder;
extern VALUE cError;
extern VALUE cParseError;
+extern VALUE map_parse_frames;
+
// We forward-declare all of the Ruby method implementations here because we
// sometimes call the methods directly across .c files, rather than going
// through Ruby's method dispatching (e.g. during message parse). It's cleaner
@@ -313,7 +315,7 @@ void native_slot_dup(upb_fieldtype_t type, void* to, void* from);
void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from);
bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2);
-void native_slot_validate_string_encoding(upb_fieldtype_t type, VALUE value);
+VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value);
void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE value);
extern rb_encoding* kRubyStringUtf8Encoding;
@@ -366,6 +368,7 @@ RepeatedField* ruby_to_RepeatedField(VALUE value);
VALUE RepeatedField_each(VALUE _self);
VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self);
void* RepeatedField_index_native(VALUE _self, int index);
+int RepeatedField_size(VALUE _self);
VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val);
void RepeatedField_reserve(RepeatedField* self, int new_size);
VALUE RepeatedField_push(VALUE _self, VALUE val);
diff --git a/ruby/ext/google/protobuf_c/repeated_field.c b/ruby/ext/google/protobuf_c/repeated_field.c
index 83afbc91..47c207a5 100644
--- a/ruby/ext/google/protobuf_c/repeated_field.c
+++ b/ruby/ext/google/protobuf_c/repeated_field.c
@@ -244,6 +244,11 @@ void* RepeatedField_index_native(VALUE _self, int index) {
return RepeatedField_memoryat(self, index, element_size);
}
+int RepeatedField_size(VALUE _self) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+ return self->size;
+}
+
/*
* Private ruby method, used by RepeatedField.pop
*/
diff --git a/ruby/ext/google/protobuf_c/storage.c b/ruby/ext/google/protobuf_c/storage.c
index 1c839781..3ff2bda6 100644
--- a/ruby/ext/google/protobuf_c/storage.c
+++ b/ruby/ext/google/protobuf_c/storage.c
@@ -117,25 +117,24 @@ void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) {
}
}
-void native_slot_validate_string_encoding(upb_fieldtype_t type, VALUE value) {
- bool bad_encoding = false;
- rb_encoding* string_encoding = rb_enc_from_index(ENCODING_GET(value));
- if (type == UPB_TYPE_STRING) {
- bad_encoding =
- string_encoding != kRubyStringUtf8Encoding &&
- string_encoding != kRubyStringASCIIEncoding;
- } else {
- bad_encoding =
- string_encoding != kRubyString8bitEncoding;
- }
- // Check that encoding is UTF-8 or ASCII (for string fields) or ASCII-8BIT
- // (for bytes fields).
- if (bad_encoding) {
- rb_raise(rb_eTypeError, "Encoding for '%s' fields must be %s (was %s)",
- (type == UPB_TYPE_STRING) ? "string" : "bytes",
- (type == UPB_TYPE_STRING) ? "UTF-8 or ASCII" : "ASCII-8BIT",
- rb_enc_name(string_encoding));
+VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value) {
+ rb_encoding* desired_encoding = (type == UPB_TYPE_STRING) ?
+ kRubyStringUtf8Encoding : kRubyString8bitEncoding;
+ VALUE desired_encoding_value = rb_enc_from_encoding(desired_encoding);
+
+ // Note: this will not duplicate underlying string data unless necessary.
+ value = rb_str_encode(value, desired_encoding_value, 0, Qnil);
+
+ if (type == UPB_TYPE_STRING &&
+ rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) {
+ rb_raise(rb_eEncodingError, "String is invalid UTF-8");
}
+
+ // Ensure the data remains valid. Since we called #encode a moment ago,
+ // this does not freeze the string the user assigned.
+ rb_obj_freeze(value);
+
+ return value;
}
void native_slot_set(upb_fieldtype_t type, VALUE type_class,
@@ -181,8 +180,8 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
if (CLASS_OF(value) != rb_cString) {
rb_raise(rb_eTypeError, "Invalid argument for string field.");
}
- native_slot_validate_string_encoding(type, value);
- DEREF(memory, VALUE) = value;
+
+ DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
break;
}
case UPB_TYPE_MESSAGE: {
diff --git a/ruby/ext/google/protobuf_c/upb.c b/ruby/ext/google/protobuf_c/upb.c
index 74a2a1db..544ebc04 100644
--- a/ruby/ext/google/protobuf_c/upb.c
+++ b/ruby/ext/google/protobuf_c/upb.c
@@ -11076,8 +11076,8 @@ static bool end_stringval(upb_json_parser *p) {
case UPB_TYPE_STRING: {
upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(&p->top->sink, sel);
p->top--;
+ upb_sink_endstr(&p->top->sink, sel);
break;
}
@@ -11175,7 +11175,7 @@ static bool parse_mapentry_key(upb_json_parser *p) {
sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
upb_sink_putstring(&subsink, sel, buf, len, NULL);
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(&subsink, sel);
+ upb_sink_endstr(&p->top->sink, sel);
multipart_end(p);
break;
}
diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec
index c542abf6..286d8fe3 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.6.0.0"
+ s.version = "3.0.0"
s.licenses = ["BSD"]
s.summary = "Protocol Buffers"
s.description = "Protocol Buffers are Google's data interchange format."
diff --git a/ruby/lib/google/protobuf.rb b/ruby/lib/google/protobuf.rb
index 62bdd1bf..9b8d8231 100644
--- a/ruby/lib/google/protobuf.rb
+++ b/ruby/lib/google/protobuf.rb
@@ -45,7 +45,7 @@ if RUBY_PLATFORM == "java"
require 'google/protobuf_java'
else
begin
- require "google/#{RUBY_VERSION.sub(/\.\d$/, '')}/protobuf_c"
+ require "google/#{RUBY_VERSION.sub(/\.\d+$/, '')}/protobuf_c"
rescue LoadError
require 'google/protobuf_c'
end
diff --git a/ruby/lib/google/protobuf/well_known_types.rb b/ruby/lib/google/protobuf/well_known_types.rb
new file mode 100644
index 00000000..547de874
--- /dev/null
+++ b/ruby/lib/google/protobuf/well_known_types.rb
@@ -0,0 +1,212 @@
+#!/usr/bin/ruby
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# https://developers.google.com/protocol-buffers/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+require 'google/protobuf/any_pb'
+require 'google/protobuf/duration_pb'
+require 'google/protobuf/field_mask_pb'
+require 'google/protobuf/struct_pb'
+require 'google/protobuf/timestamp_pb'
+
+module Google
+ module Protobuf
+
+ Any.class_eval do
+ def pack(msg, type_url_prefix='type.googleapis.com/')
+ if type_url_prefix.empty? or type_url_prefix[-1] != '/' then
+ self.type_url = "#{type_url_prefix}/#{msg.class.descriptor.name}"
+ else
+ self.type_url = "#{type_url_prefix}#{msg.class.descriptor.name}"
+ end
+ self.value = msg.to_proto
+ end
+
+ def unpack(klass)
+ if self.is(klass) then
+ klass.decode(self.value)
+ else
+ nil
+ end
+ end
+
+ def type_name
+ return self.type_url.split("/")[-1]
+ end
+
+ def is(klass)
+ return self.type_name == klass.descriptor.name
+ end
+ end
+
+ Timestamp.class_eval do
+ def to_time
+ Time.at(self.to_f)
+ end
+
+ def from_time(time)
+ self.seconds = time.to_i
+ self.nanos = time.nsec
+ end
+
+ def to_i
+ self.seconds
+ end
+
+ def to_f
+ self.seconds + (self.nanos.to_f / 1_000_000_000)
+ end
+ end
+
+ Duration.class_eval do
+ def to_f
+ self.seconds + (self.nanos.to_f / 1_000_000_000)
+ end
+ end
+
+ class UnexpectedStructType < Google::Protobuf::Error; end
+
+ Value.class_eval do
+ def to_ruby(recursive = false)
+ case self.kind
+ when :struct_value
+ if recursive
+ self.struct_value.to_h
+ else
+ self.struct_value
+ end
+ when :list_value
+ if recursive
+ self.list_value.to_a
+ else
+ self.list_value
+ end
+ when :null_value
+ nil
+ when :number_value
+ self.number_value
+ when :string_value
+ self.string_value
+ when :bool_value
+ self.bool_value
+ else
+ raise UnexpectedStructType
+ end
+ end
+
+ def from_ruby(value)
+ case value
+ when NilClass
+ self.null_value = 0
+ when Numeric
+ self.number_value = value
+ when String
+ self.string_value = value
+ when TrueClass
+ self.bool_value = true
+ when FalseClass
+ self.bool_value = false
+ when Struct
+ self.struct_value = value
+ when Hash
+ self.struct_value = Struct.from_hash(value)
+ when ListValue
+ self.list_value = value
+ when Array
+ self.list_value = ListValue.from_a(value)
+ else
+ raise UnexpectedStructType
+ end
+ end
+ end
+
+ Struct.class_eval do
+ def [](key)
+ self.fields[key].to_ruby
+ end
+
+ def []=(key, value)
+ unless key.is_a?(String)
+ raise UnexpectedStructType, "Struct keys must be strings."
+ end
+ self.fields[key] ||= Google::Protobuf::Value.new
+ self.fields[key].from_ruby(value)
+ end
+
+ def to_h
+ ret = {}
+ self.fields.each { |key, val| ret[key] = val.to_ruby(true) }
+ ret
+ end
+
+ def self.from_hash(hash)
+ ret = Struct.new
+ hash.each { |key, val| ret[key] = val }
+ ret
+ end
+ end
+
+ ListValue.class_eval do
+ include Enumerable
+
+ def length
+ self.values.length
+ end
+
+ def [](index)
+ self.values[index].to_ruby
+ end
+
+ def []=(index, value)
+ self.values[index].from_ruby(value)
+ end
+
+ def <<(value)
+ wrapper = Google::Protobuf::Value.new
+ wrapper.from_ruby(value)
+ self.values << wrapper
+ end
+
+ def each
+ self.values.each { |x| yield(x.to_ruby) }
+ end
+
+ def to_a
+ self.values.map { |x| x.to_ruby(true) }
+ end
+
+ def self.from_a(arr)
+ ret = ListValue.new
+ arr.each { |val| ret << val }
+ ret
+ end
+ end
+
+ end
+end
diff --git a/ruby/pom.xml b/ruby/pom.xml
index 4cbd6d30..99e8449b 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-3</version>
+ <version>3.0.0-beta-4</version>
</dependency>
</dependencies>
</project>
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java
index 2d4c03b5..3adaa2a8 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java
@@ -148,8 +148,8 @@ public class RubyMap extends RubyObject {
*/
@JRubyMethod(name = "[]=")
public IRubyObject indexSet(ThreadContext context, IRubyObject key, IRubyObject value) {
- Utils.checkType(context, keyType, key, (RubyModule) valueTypeClass);
- Utils.checkType(context, valueType, value, (RubyModule) valueTypeClass);
+ key = Utils.checkType(context, keyType, key, (RubyModule) valueTypeClass);
+ value = Utils.checkType(context, valueType, value, (RubyModule) valueTypeClass);
IRubyObject symbol;
if (valueType == Descriptors.FieldDescriptor.Type.ENUM &&
Utils.isRubyNum(value) &&
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
index 12893f73..462f8a69 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
@@ -504,7 +504,7 @@ public class RubyMessage extends RubyObject {
break;
case BYTES:
case STRING:
- Utils.validateStringEncoding(context.runtime, fieldDescriptor.getType(), value);
+ Utils.validateStringEncoding(context, fieldDescriptor.getType(), value);
RubyString str = (RubyString) value;
switch (fieldDescriptor.getType()) {
case BYTES:
@@ -695,7 +695,7 @@ public class RubyMessage extends RubyObject {
}
}
if (addValue) {
- Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
+ value = Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
this.fields.put(fieldDescriptor, value);
} else {
this.fields.remove(fieldDescriptor);
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
index 946f9e74..ae2907a9 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
@@ -110,7 +110,7 @@ public class RubyRepeatedField extends RubyObject {
@JRubyMethod(name = "[]=")
public IRubyObject indexSet(ThreadContext context, IRubyObject index, IRubyObject value) {
int arrIndex = normalizeArrayIndex(index);
- Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
+ value = Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
IRubyObject defaultValue = defaultValue(context);
for (int i = this.storage.size(); i < arrIndex; i++) {
this.storage.set(i, defaultValue);
@@ -166,7 +166,7 @@ public class RubyRepeatedField extends RubyObject {
public IRubyObject push(ThreadContext context, IRubyObject value) {
if (!(fieldType == Descriptors.FieldDescriptor.Type.MESSAGE &&
value == context.runtime.getNil())) {
- Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
+ value = Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
}
this.storage.add(value);
return this.storage;
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/Utils.java b/ruby/src/main/java/com/google/protobuf/jruby/Utils.java
index 596a0979..f199feb9 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/Utils.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/Utils.java
@@ -64,8 +64,8 @@ public class Utils {
return context.runtime.newSymbol(typeName.replace("TYPE_", "").toLowerCase());
}
- public static void checkType(ThreadContext context, Descriptors.FieldDescriptor.Type fieldType,
- IRubyObject value, RubyModule typeClass) {
+ public static IRubyObject checkType(ThreadContext context, Descriptors.FieldDescriptor.Type fieldType,
+ IRubyObject value, RubyModule typeClass) {
Ruby runtime = context.runtime;
Object val;
switch(fieldType) {
@@ -106,7 +106,7 @@ public class Utils {
break;
case BYTES:
case STRING:
- validateStringEncoding(context.runtime, fieldType, value);
+ value = validateStringEncoding(context, fieldType, value);
break;
case MESSAGE:
if (value.getMetaClass() != typeClass) {
@@ -127,6 +127,7 @@ public class Utils {
default:
break;
}
+ return value;
}
public static IRubyObject wrapPrimaryValue(ThreadContext context, Descriptors.FieldDescriptor.Type fieldType, Object value) {
@@ -148,10 +149,16 @@ public class Utils {
return runtime.newFloat((Double) value);
case BOOL:
return (Boolean) value ? runtime.getTrue() : runtime.getFalse();
- case BYTES:
- return runtime.newString(((ByteString) value).toStringUtf8());
- case STRING:
- return runtime.newString(value.toString());
+ case BYTES: {
+ IRubyObject wrapped = runtime.newString(((ByteString) value).toStringUtf8());
+ wrapped.setFrozen(true);
+ return wrapped;
+ }
+ case STRING: {
+ IRubyObject wrapped = runtime.newString(value.toString());
+ wrapped.setFrozen(true);
+ return wrapped;
+ }
default:
return runtime.getNil();
}
@@ -180,25 +187,21 @@ public class Utils {
}
}
- public static void validateStringEncoding(Ruby runtime, Descriptors.FieldDescriptor.Type type, IRubyObject value) {
+ public static IRubyObject validateStringEncoding(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value) {
if (!(value instanceof RubyString))
- throw runtime.newTypeError("Invalid argument for string field.");
- Encoding encoding = ((RubyString) value).getEncoding();
+ throw context.runtime.newTypeError("Invalid argument for string field.");
switch(type) {
case BYTES:
- if (encoding != ASCIIEncoding.INSTANCE)
- throw runtime.newTypeError("Encoding for bytes fields" +
- " must be \"ASCII-8BIT\", but was " + encoding);
+ value = ((RubyString)value).encode(context, context.runtime.evalScriptlet("Encoding::ASCII_8BIT"));
break;
case STRING:
- if (encoding != UTF8Encoding.INSTANCE
- && encoding != USASCIIEncoding.INSTANCE)
- throw runtime.newTypeError("Encoding for string fields" +
- " must be \"UTF-8\" or \"ASCII\", but was " + encoding);
+ value = ((RubyString)value).encode(context, context.runtime.evalScriptlet("Encoding::UTF_8"));
break;
default:
break;
}
+ value.setFrozen(true);
+ return value;
}
public static void checkNameAvailability(ThreadContext context, String name) {
diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb
index fee07e33..8b6d329e 100644
--- a/ruby/tests/basic.rb
+++ b/ruby/tests/basic.rb
@@ -255,14 +255,17 @@ module BasicTest
m = TestMessage.new
# Assigning a normal (ASCII or UTF8) string to a bytes field, or
- # ASCII-8BIT to a string field, raises an error.
- assert_raise TypeError do
- m.optional_bytes = "Test string ASCII".encode!('ASCII')
- end
- assert_raise TypeError do
+ # ASCII-8BIT to a string field will convert to the proper encoding.
+ m.optional_bytes = "Test string ASCII".encode!('ASCII')
+ assert m.optional_bytes.frozen?
+ assert_equal Encoding::ASCII_8BIT, m.optional_bytes.encoding
+ assert_equal "Test string ASCII", m.optional_bytes
+
+ assert_raise Encoding::UndefinedConversionError do
m.optional_bytes = "Test string UTF-8 \u0100".encode!('UTF-8')
end
- assert_raise TypeError do
+
+ assert_raise Encoding::UndefinedConversionError do
m.optional_string = ["FFFF"].pack('H*')
end
@@ -270,11 +273,10 @@ module BasicTest
m.optional_bytes = ["FFFF"].pack('H*')
m.optional_string = "\u0100"
- # strings are mutable so we can do this, but serialize should catch it.
+ # strings are immutable so we can't do this, but serialize should catch it.
m.optional_string = "asdf".encode!('UTF-8')
- m.optional_string.encode!('ASCII-8BIT')
- assert_raise TypeError do
- data = TestMessage.encode(m)
+ assert_raise RuntimeError do
+ m.optional_string.encode!('ASCII-8BIT')
end
end
@@ -466,9 +468,9 @@ module BasicTest
assert m.length == 2
m2 = m.dup
- assert m == m2
+ assert_equal m, m2
assert m.hash != 0
- assert m.hash == m2.hash
+ assert_equal m.hash, m2.hash
collected = {}
m.each { |k,v| collected[v] = k }
@@ -558,7 +560,7 @@ module BasicTest
assert_raise TypeError do
m[1] = 1
end
- assert_raise TypeError do
+ assert_raise Encoding::UndefinedConversionError do
bytestring = ["FFFF"].pack("H*")
m[bytestring] = 1
end
@@ -566,9 +568,8 @@ module BasicTest
m = Google::Protobuf::Map.new(:bytes, :int32)
bytestring = ["FFFF"].pack("H*")
m[bytestring] = 1
- assert_raise TypeError do
- m["asdf"] = 1
- end
+ # Allowed -- we will automatically convert to ASCII-8BIT.
+ m["asdf"] = 1
assert_raise TypeError do
m[1] = 1
end
@@ -853,15 +854,22 @@ module BasicTest
def test_encode_decode_helpers
m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
+ assert_equal 'foo', m.optional_string
+ assert_equal ['bar1', 'bar2'], m.repeated_string
+
json = m.to_json
m2 = TestMessage.decode_json(json)
- assert m2.optional_string == 'foo'
- assert m2.repeated_string == ['bar1', 'bar2']
+ assert_equal 'foo', m2.optional_string
+ assert_equal ['bar1', 'bar2'], m2.repeated_string
+ if RUBY_PLATFORM != "java"
+ assert m2.optional_string.frozen?
+ assert m2.repeated_string[0].frozen?
+ end
proto = m.to_proto
m2 = TestMessage.decode(proto)
- assert m2.optional_string == 'foo'
- assert m2.repeated_string == ['bar1', 'bar2']
+ assert_equal 'foo', m2.optional_string
+ assert_equal ['bar1', 'bar2'], m2.repeated_string
end
def test_protobuf_encode_decode_helpers
diff --git a/ruby/tests/generated_code.proto b/ruby/tests/generated_code.proto
index 42d82a6b..62fd83ed 100644
--- a/ruby/tests/generated_code.proto
+++ b/ruby/tests/generated_code.proto
@@ -1,6 +1,6 @@
syntax = "proto3";
-package A.B.C;
+package a.b.c;
message TestMessage {
int32 optional_int32 = 1;
diff --git a/ruby/tests/generated_code_test.rb b/ruby/tests/generated_code_test.rb
index daef357a..b92b0462 100644
--- a/ruby/tests/generated_code_test.rb
+++ b/ruby/tests/generated_code_test.rb
@@ -3,7 +3,8 @@
# generated_code.rb is in the same directory as this test.
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
-require 'generated_code'
+require 'generated_code_pb'
+require 'test_import_pb'
require 'test/unit'
class GeneratedCodeTest < Test::Unit::TestCase
@@ -13,5 +14,6 @@ class GeneratedCodeTest < Test::Unit::TestCase
# successfully creates message definitions and classes, not to test every
# aspect of the extension (basic.rb is for that).
m = A::B::C::TestMessage.new()
+ m2 = FooBar::TestImportedMessage.new()
end
end
diff --git a/ruby/tests/test_import.proto b/ruby/tests/test_import.proto
new file mode 100644
index 00000000..230484ee
--- /dev/null
+++ b/ruby/tests/test_import.proto
@@ -0,0 +1,5 @@
+syntax = "proto3";
+
+package foo_bar;
+
+message TestImportedMessage {}
diff --git a/ruby/tests/well_known_types_test.rb b/ruby/tests/well_known_types_test.rb
new file mode 100644
index 00000000..9b46632b
--- /dev/null
+++ b/ruby/tests/well_known_types_test.rb
@@ -0,0 +1,122 @@
+#!/usr/bin/ruby
+
+require 'test/unit'
+require 'google/protobuf/well_known_types'
+
+class TestWellKnownTypes < Test::Unit::TestCase
+ def test_timestamp
+ ts = Google::Protobuf::Timestamp.new
+
+ assert_equal Time.at(0), ts.to_time
+
+ ts.seconds = 12345
+ assert_equal Time.at(12345), ts.to_time
+ assert_equal 12345, ts.to_i
+
+ ts.from_time(Time.at(123456, 654321))
+ assert_equal 123456, ts.seconds
+ assert_equal 654321000, ts.nanos
+ assert_equal Time.at(123456.654321), ts.to_time
+ end
+
+ def test_duration
+ duration = Google::Protobuf::Duration.new(seconds: 123, nanos: 456)
+ assert_equal 123.000000456, duration.to_f
+ end
+
+ def test_struct
+ struct = Google::Protobuf::Struct.new
+
+ substruct = {
+ "subkey" => 999,
+ "subkey2" => false
+ }
+
+ sublist = ["abc", 123, {"deepkey" => "deepval"}]
+
+ struct["number"] = 12345
+ struct["boolean-true"] = true
+ struct["boolean-false"] = false
+ struct["null"] = nil
+ struct["string"] = "abcdef"
+ struct["substruct"] = substruct
+ struct["sublist"] = sublist
+
+ assert_equal 12345, struct["number"]
+ assert_equal true, struct["boolean-true"]
+ assert_equal false, struct["boolean-false"]
+ assert_equal nil, struct["null"]
+ assert_equal "abcdef", struct["string"]
+ assert_equal(Google::Protobuf::Struct.from_hash(substruct),
+ struct["substruct"])
+ assert_equal(Google::Protobuf::ListValue.from_a(sublist),
+ struct["sublist"])
+
+ should_equal = {
+ "number" => 12345,
+ "boolean-true" => true,
+ "boolean-false" => false,
+ "null" => nil,
+ "string" => "abcdef",
+ "substruct" => {
+ "subkey" => 999,
+ "subkey2" => false
+ },
+ "sublist" => ["abc", 123, {"deepkey" => "deepval"}]
+ }
+
+ list = struct["sublist"]
+ list.is_a?(Google::Protobuf::ListValue)
+ assert_equal "abc", list[0]
+ assert_equal 123, list[1]
+ assert_equal({"deepkey" => "deepval"}, list[2].to_h)
+
+ # to_h returns a fully-flattened Ruby structure (Hash and Array).
+ assert_equal(should_equal, struct.to_h)
+
+ # Test that we can assign Struct and ListValue directly.
+ struct["substruct"] = Google::Protobuf::Struct.from_hash(substruct)
+ struct["sublist"] = Google::Protobuf::ListValue.from_a(sublist)
+
+ assert_equal(should_equal, struct.to_h)
+
+ struct["sublist"] << nil
+ should_equal["sublist"] << nil
+
+ assert_equal(should_equal, struct.to_h)
+ assert_equal(should_equal["sublist"].length, struct["sublist"].length)
+
+ assert_raise Google::Protobuf::UnexpectedStructType do
+ struct[123] = 5
+ end
+
+ assert_raise Google::Protobuf::UnexpectedStructType do
+ struct[5] = Time.new
+ end
+
+ assert_raise Google::Protobuf::UnexpectedStructType do
+ struct[5] = [Time.new]
+ end
+
+ assert_raise Google::Protobuf::UnexpectedStructType do
+ struct[5] = {123 => 456}
+ end
+
+ assert_raise Google::Protobuf::UnexpectedStructType do
+ struct = Google::Protobuf::Struct.new
+ struct.fields["foo"] = Google::Protobuf::Value.new
+ # Tries to return a Ruby value for a Value class whose type
+ # hasn't been filled in.
+ struct["foo"]
+ end
+ end
+
+ def test_any
+ any = Google::Protobuf::Any.new
+ ts = Google::Protobuf::Timestamp.new(seconds: 12345, nanos: 6789)
+ any.pack(ts)
+
+ assert any.is(Google::Protobuf::Timestamp)
+ assert_equal ts, any.unpack(Google::Protobuf::Timestamp)
+ end
+end
diff --git a/ruby/travis-test.sh b/ruby/travis-test.sh
index 75db7d93..59e970a6 100755
--- a/ruby/travis-test.sh
+++ b/ruby/travis-test.sh
@@ -5,7 +5,7 @@ set -e
test_version() {
version=$1
- if [ "$version" == "jruby" ] ; then
+ if [ "$version" == "jruby-1.7" ] ; then
# No conformance tests yet -- JRuby is too broken to run them.
bash --login -c \
"rvm install $version && rvm use $version && \
diff --git a/src/Makefile.am b/src/Makefile.am
index b75b6f74..f70e9550 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,8 +19,9 @@ PTHREAD_DEF =
endif
if GCC
-# These are good warnings to turn on by default
-NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF) -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare
+# Turn on all warnings except for sign comparison (we ignore sign comparison
+# in Google so our code base have tons of such warnings).
+NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF) -Wall -Wno-sign-compare
else
NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF)
endif
@@ -32,6 +33,10 @@ AM_LDFLAGS = $(PTHREAD_CFLAGS)
# If I say "dist_include_DATA", automake complains that $(includedir) is not
# a "legitimate" directory for DATA. Screw you, automake.
protodir = $(includedir)
+
+# If you are adding new files here, also remember to change the build files for
+# all other languages, //protoc-artifacts/build-zip.sh and run
+# //update_file_list.sh for bazel.
nobase_dist_proto_DATA = google/protobuf/descriptor.proto \
google/protobuf/any.proto \
google/protobuf/api.proto \
@@ -50,7 +55,8 @@ clean-local:
rm -f *.loT
CLEANFILES = $(protoc_outputs) unittest_proto_middleman \
- testzip.jar testzip.list testzip.proto testzip.zip
+ testzip.jar testzip.list testzip.proto testzip.zip \
+ no_warning_test.cc
MAINTAINERCLEANFILES = \
Makefile.in
@@ -59,6 +65,7 @@ nobase_include_HEADERS = \
google/protobuf/stubs/atomic_sequence_num.h \
google/protobuf/stubs/atomicops.h \
google/protobuf/stubs/atomicops_internals_power.h \
+ google/protobuf/stubs/atomicops_internals_ppc_gcc.h \
google/protobuf/stubs/atomicops_internals_arm64_gcc.h \
google/protobuf/stubs/atomicops_internals_arm_gcc.h \
google/protobuf/stubs/atomicops_internals_arm_qnx.h \
@@ -121,7 +128,6 @@ nobase_include_HEADERS = \
google/protobuf/reflection.h \
google/protobuf/reflection_ops.h \
google/protobuf/repeated_field.h \
- google/protobuf/repeated_field_reflection.h \
google/protobuf/service.h \
google/protobuf/source_context.pb.h \
google/protobuf/struct.pb.h \
@@ -530,6 +536,7 @@ EXTRA_DIST = \
google/protobuf/io/gzip_stream.h \
google/protobuf/io/gzip_stream_unittest.sh \
google/protobuf/testdata/golden_message \
+ google/protobuf/testdata/golden_message_maps \
google/protobuf/testdata/golden_message_oneof_implemented \
google/protobuf/testdata/golden_message_proto3 \
google/protobuf/testdata/golden_packed_fields_message \
@@ -544,9 +551,10 @@ EXTRA_DIST = \
google/protobuf/package_info.h \
google/protobuf/io/package_info.h \
google/protobuf/compiler/ruby/ruby_generated_code.proto \
- google/protobuf/compiler/ruby/ruby_generated_code.rb \
+ google/protobuf/compiler/ruby/ruby_generated_code_pb.rb \
google/protobuf/compiler/package_info.h \
- google/protobuf/compiler/zip_output_unittest.sh
+ google/protobuf/compiler/zip_output_unittest.sh \
+ README.md
protoc_lite_outputs = \
google/protobuf/map_lite_unittest.pb.cc \
@@ -677,7 +685,7 @@ COMMON_TEST_SOURCES = \
check_PROGRAMS = protoc protobuf-test protobuf-lazy-descriptor-test \
protobuf-lite-test test_plugin protobuf-lite-arena-test \
- $(GZCHECKPROGRAMS)
+ no-warning-test $(GZCHECKPROGRAMS)
protobuf_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \
../gmock/gtest/lib/libgtest.la \
../gmock/lib/libgmock.la \
@@ -830,6 +838,27 @@ zcgunzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la
zcgunzip_SOURCES = google/protobuf/testing/zcgunzip.cc
endif
+# This test target is to ensure all our public header files and generated
+# code is free from warnings. We have to be more pedantic about these
+# files because they are compiled by users with different compiler flags.
+no_warning_test.cc:
+ echo "// Generated from Makefile.am" > no_warning_test.cc
+ for FILE in $(nobase_include_HEADERS); do \
+ if ! echo $${FILE} | grep "atomicops"; then \
+ echo "#include <$${FILE}>" >> no_warning_test.cc; \
+ fi \
+ done
+ echo "#include <gtest/gtest.h>" >> no_warning_test.cc
+ echo "TEST(NoWarningTest, Empty) {}" >> no_warning_test.cc
+
+no_warning_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la \
+ ../gmock/gtest/lib/libgtest.la \
+ ../gmock/gtest/lib/libgtest_main.la
+no_warning_test_CPPFLAGS = -I$(srcdir)/../gmock/gtest/include
+no_warning_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF) \
+ -Wall -Werror
+nodist_no_warning_test_SOURCES = no_warning_test.cc $(protoc_outputs)
+
TESTS = protobuf-test protobuf-lazy-descriptor-test protobuf-lite-test \
google/protobuf/compiler/zip_output_unittest.sh $(GZTESTS) \
- protobuf-lite-arena-test
+ protobuf-lite-arena-test no-warning-test
diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc
index c91faa08..ccccc9c1 100644
--- a/src/google/protobuf/any.pb.cc
+++ b/src/google/protobuf/any.pb.cc
@@ -29,6 +29,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
} // namespace
+void protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto() {
protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
const ::google::protobuf::FileDescriptor* file =
@@ -61,6 +62,7 @@ inline void protobuf_AssignDescriptorsOnce() {
&protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto);
}
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
@@ -74,6 +76,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fany_2eproto() {
delete Any_reflection_;
}
+void protobuf_AddDesc_google_2fprotobuf_2fany_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AddDesc_google_2fprotobuf_2fany_2eproto() {
static bool already_here = false;
if (already_here) return;
@@ -101,16 +104,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fany_2eproto {
}
} static_descriptor_initializer_google_2fprotobuf_2fany_2eproto_;
-namespace {
-
-static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
-static void MergeFromFail(int line) {
- GOOGLE_CHECK(false) << __FILE__ << ":" << line;
-}
-
-} // namespace
-
-
// ===================================================================
void Any::PackFrom(const ::google::protobuf::Message& message) {
@@ -334,7 +327,9 @@ int Any::ByteSize() const {
void Any::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Any)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const Any* source =
::google::protobuf::internal::DynamicCastToGenerated<const Any>(
&from);
@@ -349,7 +344,9 @@ void Any::MergeFrom(const ::google::protobuf::Message& from) {
void Any::MergeFrom(const Any& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Any)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.type_url().size() > 0) {
type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_);
diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc
index d5dd8923..e8c2a178 100644
--- a/src/google/protobuf/api.pb.cc
+++ b/src/google/protobuf/api.pb.cc
@@ -35,6 +35,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
} // namespace
+void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto() {
protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
const ::google::protobuf::FileDescriptor* file =
@@ -109,6 +110,7 @@ inline void protobuf_AssignDescriptorsOnce() {
&protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto);
}
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
@@ -130,6 +132,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto() {
delete Mixin_reflection_;
}
+void protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto() {
static bool already_here = false;
if (already_here) return;
@@ -175,16 +178,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fapi_2eproto {
}
} static_descriptor_initializer_google_2fprotobuf_2fapi_2eproto_;
-namespace {
-
-static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
-static void MergeFromFail(int line) {
- GOOGLE_CHECK(false) << __FILE__ << ":" << line;
-}
-
-} // namespace
-
-
// ===================================================================
#if !defined(_MSC_VER) || _MSC_VER >= 1900
@@ -601,7 +594,9 @@ int Api::ByteSize() const {
void Api::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Api)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const Api* source =
::google::protobuf::internal::DynamicCastToGenerated<const Api>(
&from);
@@ -616,7 +611,9 @@ void Api::MergeFrom(const ::google::protobuf::Message& from) {
void Api::MergeFrom(const Api& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Api)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
methods_.MergeFrom(from.methods_);
options_.MergeFrom(from.options_);
mixins_.MergeFrom(from.mixins_);
@@ -1008,7 +1005,7 @@ void Method::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -1345,7 +1342,9 @@ int Method::ByteSize() const {
void Method::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Method)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const Method* source =
::google::protobuf::internal::DynamicCastToGenerated<const Method>(
&from);
@@ -1360,7 +1359,9 @@ void Method::MergeFrom(const ::google::protobuf::Message& from) {
void Method::MergeFrom(const Method& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Method)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
options_.MergeFrom(from.options_);
if (from.name().size() > 0) {
@@ -1858,7 +1859,9 @@ int Mixin::ByteSize() const {
void Mixin::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Mixin)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const Mixin* source =
::google::protobuf::internal::DynamicCastToGenerated<const Mixin>(
&from);
@@ -1873,7 +1876,9 @@ void Mixin::MergeFrom(const ::google::protobuf::Message& from) {
void Mixin::MergeFrom(const Mixin& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Mixin)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.name().size() > 0) {
name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index 0ebf9b6a..dee438c6 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -719,6 +719,11 @@ TEST_F(CommandLineInterfaceTest, TrailingBackslash) {
ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
+TEST_F(CommandLineInterfaceTest, Win32ErrorMessage) {
+ EXPECT_EQ("The system cannot find the file specified.\r\n",
+ Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND));
+}
+
#endif // defined(_WIN32) || defined(__CYGWIN__)
TEST_F(CommandLineInterfaceTest, PathLookup) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index 385b973e..b3eca660 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -336,19 +336,6 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
// Generate classes.
for (int i = 0; i < file_->message_type_count(); i++) {
- if (i == 0 && HasGeneratedMethods(file_, options_)) {
- printer->Print(
- "\n"
- "namespace {\n"
- "\n"
- "static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;\n"
- "static void MergeFromFail(int line) {\n"
- " GOOGLE_CHECK(false) << __FILE__ << \":\" << line;\n"
- "}\n"
- "\n"
- "} // namespace\n"
- "\n");
- }
printer->Print("\n");
printer->Print(kThickSeparator);
printer->Print("\n");
@@ -464,9 +451,10 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// and we only use AddDescriptors() to allocate default instances.
if (HasDescriptorMethods(file_, options_)) {
printer->Print(
- "\n"
- "void $assigndescriptorsname$() {\n",
- "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
+ "\n"
+ "void $assigndescriptorsname$() GOOGLE_ATTRIBUTE_COLD;\n"
+ "void $assigndescriptorsname$() {\n",
+ "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
printer->Indent();
// Make sure the file has found its way into the pool. If a descriptor
@@ -525,8 +513,9 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// protobuf_RegisterTypes(): Calls
// MessageFactory::InternalRegisterGeneratedType() for each message type.
printer->Print(
- "void protobuf_RegisterTypes(const ::std::string&) {\n"
- " protobuf_AssignDescriptorsOnce();\n");
+ "void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;\n"
+ "void protobuf_RegisterTypes(const ::std::string&) {\n"
+ " protobuf_AssignDescriptorsOnce();\n");
printer->Indent();
for (int i = 0; i < file_->message_type_count(); i++) {
@@ -566,6 +555,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// Note that we don't need any special synchronization in the following
// code
// because it is called at static init time before any threads exist.
+ "void $adddescriptorsname$() GOOGLE_ATTRIBUTE_COLD;\n"
"void $adddescriptorsname$() {\n"
" static bool already_here = false;\n"
" if (already_here) return;\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index dd9f1887..0588e34e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -251,117 +251,148 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
}
}
-void MapFieldGenerator::
-GenerateSerializeWithCachedSizes(io::Printer* printer) const {
- printer->Print(variables_,
- "{\n"
- " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
- " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
- " it = this->$name$().begin();\n"
- " it != this->$name$().end(); ++it) {\n");
+static void GenerateSerializationLoop(io::Printer* printer,
+ const map<string, string>& variables,
+ bool supports_arenas,
+ const string& utf8_check,
+ const string& loop_header,
+ const string& ptr,
+ bool loop_via_iterators) {
+ printer->Print(variables,
+ StrCat("::google::protobuf::scoped_ptr<$map_classname$> entry;\n",
+ loop_header, " {\n").c_str());
+ printer->Indent();
+
+ printer->Print(variables, StrCat(
+ "entry.reset($name$_.New$wrapper$(\n"
+ " ", ptr, "->first, ", ptr, "->second));\n"
+ "$write_entry$;\n").c_str());
// If entry is allocated by arena, its desctructor should be avoided.
- if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
- " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
- " entry.release();\n"
- " }\n");
+ if (supports_arenas) {
+ printer->Print(
+ "if (entry->GetArena() != NULL) {\n"
+ " entry.release();\n"
+ "}\n");
}
- 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");
-
- 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, options_, false, variables_,
- "it->first.data(), it->first.length(),\n",
- printer);
- }
- if (value_field->type() == FieldDescriptor::TYPE_STRING) {
- GenerateUtf8CheckCodeForString(value_field, options_, false, variables_,
- "it->second.data(), it->second.length(),\n",
- printer);
+ if (!utf8_check.empty()) {
+ // If loop_via_iterators is true then ptr is actually an iterator, and we
+ // create a pointer by prefixing it with "&*".
+ printer->Print(
+ StrCat(utf8_check, "(", (loop_via_iterators ? "&*" : ""), ptr, ");\n")
+ .c_str());
}
printer->Outdent();
- printer->Outdent();
-
printer->Print(
- " }\n");
-
- // If entry is allocated by arena, its desctructor should be avoided.
- if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
- " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
- " entry.release();\n"
- " }\n");
- }
+ "}\n");
+}
- printer->Print("}\n");
+void MapFieldGenerator::
+GenerateSerializeWithCachedSizes(io::Printer* printer) const {
+ map<string, string> variables(variables_);
+ variables["write_entry"] = "::google::protobuf::internal::WireFormatLite::Write" +
+ variables["stream_writer"] + "(\n " +
+ variables["number"] + ", *entry, output)";
+ variables["deterministic"] = "output->IsSerializationDeterminstic()";
+ GenerateSerializeWithCachedSizes(printer, variables);
}
void MapFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
- printer->Print(variables_,
- "{\n"
- " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
- " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
- " it = this->$name$().begin();\n"
- " it != this->$name$().end(); ++it) {\n");
-
- // If entry is allocated by arena, its desctructor should be avoided.
- if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
- " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
- " entry.release();\n"
- " }\n");
- }
-
- printer->Print(variables_,
- " entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
- " target = ::google::protobuf::internal::WireFormatLite::\n"
- " InternalWrite$declared_type$NoVirtualToArray(\n"
- " $number$, *entry, false, target);\n");
+ map<string, string> variables(variables_);
+ variables["write_entry"] =
+ "target = ::google::protobuf::internal::WireFormatLite::\n"
+ " InternalWrite" + variables["declared_type"] +
+ "NoVirtualToArray(\n " + variables["number"] +
+ ", *entry, deterministic, target);\n";
+ variables["deterministic"] = "deterministic";
+ GenerateSerializeWithCachedSizes(printer, variables);
+}
+void MapFieldGenerator::GenerateSerializeWithCachedSizes(
+ io::Printer* printer, const map<string, string>& variables) const {
+ printer->Print(variables,
+ "if (!this->$name$().empty()) {\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, options_, false, variables_,
- "it->first.data(), it->first.length(),\n",
- printer);
+ const bool string_key = key_field->type() == FieldDescriptor::TYPE_STRING;
+ const bool string_value = value_field->type() == FieldDescriptor::TYPE_STRING;
+
+ printer->Print(variables,
+ "typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_pointer\n"
+ " ConstPtr;\n");
+ if (string_key) {
+ printer->Print(variables,
+ "typedef ConstPtr SortItem;\n"
+ "typedef ::google::protobuf::internal::"
+ "CompareByDerefFirst<SortItem> Less;\n");
+ } else {
+ printer->Print(variables,
+ "typedef ::google::protobuf::internal::SortItem< $key_cpp$, ConstPtr > "
+ "SortItem;\n"
+ "typedef ::google::protobuf::internal::CompareByFirstField<SortItem> Less;\n");
}
- if (value_field->type() == FieldDescriptor::TYPE_STRING) {
- GenerateUtf8CheckCodeForString(value_field, options_, false, variables_,
- "it->second.data(), it->second.length(),\n",
- printer);
+ string utf8_check;
+ if (string_key || string_value) {
+ printer->Print(
+ "struct Utf8Check {\n"
+ " static void Check(ConstPtr p) {\n");
+ printer->Indent();
+ printer->Indent();
+ if (string_key) {
+ GenerateUtf8CheckCodeForString(key_field, options_, false, variables,
+ "p->first.data(), p->first.length(),\n",
+ printer);
+ }
+ if (string_value) {
+ GenerateUtf8CheckCodeForString(value_field, options_, false, variables,
+ "p->second.data(), p->second.length(),\n",
+ printer);
+ }
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n"
+ "};\n");
+ utf8_check = "Utf8Check::Check";
}
- printer->Outdent();
+ printer->Print(variables,
+ "\n"
+ "if ($deterministic$ &&\n"
+ " this->$name$().size() > 1) {\n"
+ " ::google::protobuf::scoped_array<SortItem> items(\n"
+ " new SortItem[this->$name$().size()]);\n"
+ " typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::size_type size_type;\n"
+ " size_type n = 0;\n"
+ " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
+ " it = this->$name$().begin();\n"
+ " it != this->$name$().end(); ++it, ++n) {\n"
+ " items[n] = SortItem(&*it);\n"
+ " }\n"
+ " ::std::sort(&items[0], &items[n], Less());\n");
+ printer->Indent();
+ GenerateSerializationLoop(printer, variables, SupportsArenas(descriptor_),
+ utf8_check, "for (size_type i = 0; i < n; i++)",
+ string_key ? "items[i]" : "items[i].second", false);
printer->Outdent();
printer->Print(
- " }\n");
-
- // If entry is allocated by arena, its desctructor should be avoided.
- if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
- " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
- " entry.release();\n"
- " }\n");
- }
-
+ "} else {\n");
+ printer->Indent();
+ GenerateSerializationLoop(
+ printer, variables, SupportsArenas(descriptor_), utf8_check,
+ "for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
+ " it = this->$name$().begin();\n"
+ " it != this->$name$().end(); ++it)",
+ "it", true);
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Outdent();
printer->Print("}\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h
index 087dcde0..2930fe59 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h
@@ -61,6 +61,10 @@ class MapFieldGenerator : public FieldGenerator {
void GenerateByteSize(io::Printer* printer) const;
private:
+ // A helper for GenerateSerializeWithCachedSizes{,ToArray}.
+ void GenerateSerializeWithCachedSizes(
+ io::Printer* printer, const map<string, string>& variables) const;
+
const FieldDescriptor* descriptor_;
const bool dependent_field_;
map<string, string> variables_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 32f63152..69cd5f3c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -2419,7 +2419,7 @@ GenerateClear(io::Printer* printer) {
" &reinterpret_cast<$classname$*>(16)->f)\n"
"#endif\n\n"
"#define ZR_(first, last) do {\\\n"
- " ::memset(&first, 0,\\\n"
+ " ::memset(&(first), 0,\\\n"
" ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\\\n"
"} while (0)\n\n";
for (int i = 0; i < runs_of_fields_.size(); i++) {
@@ -2715,7 +2715,9 @@ GenerateMergeFrom(io::Printer* printer) {
"void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n"
"// @@protoc_insertion_point(generalized_merge_from_start:"
"$full_name$)\n"
- " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
+ " if (GOOGLE_PREDICT_FALSE(&from == this)) {\n"
+ " ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);\n"
+ " }\n",
"classname", classname_, "full_name", descriptor_->full_name());
printer->Indent();
@@ -2756,7 +2758,9 @@ GenerateMergeFrom(io::Printer* printer) {
"void $classname$::MergeFrom(const $classname$& from) {\n"
"// @@protoc_insertion_point(class_specific_merge_from_start:"
"$full_name$)\n"
- " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
+ " if (GOOGLE_PREDICT_FALSE(&from == this)) {\n"
+ " ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);\n"
+ " }\n",
"classname", classname_, "full_name", descriptor_->full_name());
printer->Indent();
@@ -2952,7 +2956,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
// on the CodedOutputStream.
printer->Print(
" ::google::protobuf::io::LazyStringOutputStream unknown_fields_string(\n"
- " ::google::protobuf::internal::NewPermanentCallback(\n"
+ " ::google::protobuf::NewPermanentCallback(\n"
" &MutableUnknownFieldsFor$classname$, this));\n"
" ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n"
" &unknown_fields_string, false);\n",
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 5d82946d..b7b6039a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -1252,7 +1252,7 @@ class GeneratedServiceTest : public testing::Test {
foo_(descriptor_->FindMethodByName("Foo")),
bar_(descriptor_->FindMethodByName("Bar")),
stub_(&mock_channel_),
- done_(::google::protobuf::internal::NewPermanentCallback(&DoNothing)) {}
+ done_(NewPermanentCallback(&DoNothing)) {}
virtual void SetUp() {
ASSERT_TRUE(foo_ != NULL);
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc
index 64381d0f..9e4da1ed 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc
@@ -68,9 +68,7 @@ void EnumGenerator::Generate(io::Printer* printer) {
for (int i = 0; i < descriptor_->value_count(); i++) {
WriteEnumValueDocComment(printer, descriptor_->value(i));
string original_name = descriptor_->value(i)->name();
- string name = options()->legacy_enum_values
- ? descriptor_->value(i)->name()
- : GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name());
+ string name = GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name());
// Make sure we don't get any duplicate names due to prefix removal.
while (!used_names.insert(name).second) {
// It's possible we'll end up giving this warning multiple times, but that's better than not at all.
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc
index d74e8c88..c13ed65b 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc
@@ -83,9 +83,6 @@ bool Generator::Generate(
cli_options.base_namespace_specified = true;
} else if (options[i].first == "internal_access") {
cli_options.internal_access = true;
- } else if (options[i].first == "legacy_enum_values") {
- // TODO: Remove this before final release
- cli_options.legacy_enum_values = true;
} else {
*error = "Unknown generator option: " + options[i].first;
return false;
diff --git a/src/google/protobuf/compiler/csharp/csharp_options.h b/src/google/protobuf/compiler/csharp/csharp_options.h
index 4079bf7f..426fb3b5 100644
--- a/src/google/protobuf/compiler/csharp/csharp_options.h
+++ b/src/google/protobuf/compiler/csharp/csharp_options.h
@@ -45,8 +45,7 @@ struct Options {
file_extension(".cs"),
base_namespace(""),
base_namespace_specified(false),
- internal_access(false),
- legacy_enum_values(false) {
+ internal_access(false) {
}
// Extension of the generated file. Defaults to ".cs"
string file_extension;
@@ -69,12 +68,6 @@ struct Options {
// Whether the generated classes should have accessibility level of "internal".
// Defaults to false that generates "public" classes.
bool internal_access;
- // By default, C# codegen now uses PascalCased enum values names, after
- // removing the enum type name as a prefix (if it *is* a prefix of the value).
- // Setting this option reverts to the previous behavior of just copying the
- // value name specified in the .proto file, allowing gradual migration.
- // This option will be removed before final release.
- bool legacy_enum_values;
};
} // namespace csharp
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index a06c5f6d..5e387285 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -266,9 +266,7 @@ void FileGenerator::Generate(io::Printer* printer) {
printer->Print(
"public static void registerAllExtensions(\n"
- " com.google.protobuf.ExtensionRegistry$lite$ registry) {\n",
- "lite",
- HasDescriptorMethods(file_, context_->EnforceLite()) ? "" : "Lite");
+ " com.google.protobuf.ExtensionRegistryLite registry) {\n");
printer->Indent();
@@ -283,6 +281,20 @@ void FileGenerator::Generate(io::Printer* printer) {
printer->Outdent();
printer->Print(
"}\n");
+ if (HasDescriptorMethods(file_, context_->EnforceLite())) {
+ // Overload registerAllExtensions for the non-lite usage to
+ // redundantly maintain the original signature (this is
+ // redundant because ExtensionRegistryLite now invokes
+ // ExtensionRegistry in the non-lite usage). Intent is
+ // to remove this in the future.
+ printer->Print(
+ "\n"
+ "public static void registerAllExtensions(\n"
+ " com.google.protobuf.ExtensionRegistry registry) {\n"
+ " registerAllExtensions(\n"
+ " (com.google.protobuf.ExtensionRegistryLite) registry);\n"
+ "}\n");
+ }
// -----------------------------------------------------------------
diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc
index 3c545e15..b1ab4043 100644
--- a/src/google/protobuf/compiler/java/java_generator.cc
+++ b/src/google/protobuf/compiler/java/java_generator.cc
@@ -79,8 +79,6 @@ bool JavaGenerator::Generate(const FileDescriptor* file,
file_options.generate_mutable_code = true;
} else if (options[i].first == "shared") {
file_options.generate_shared_code = true;
- } else if (options[i].first == "lite") {
- file_options.enforce_lite = true;
} else if (options[i].first == "annotate_code") {
file_options.annotate_code = true;
} else if (options[i].first == "annotation_list_file") {
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index d55a9849..6c80d070 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -205,9 +205,10 @@ GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate) {
} else {
vars["final"] = "";
}
+ vars["ver"] = GeneratedCodeVersionSuffix();
printer->Print(vars,
"$private$static $final$\n"
- " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+ " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
" internal_$identifier$_fieldAccessorTable;\n");
// 6 bytes per field and oneof
@@ -220,11 +221,11 @@ GenerateFieldAccessorTableInitializer(io::Printer* printer) {
int bytecode_estimate = 10;
printer->Print(
"internal_$identifier$_fieldAccessorTable = new\n"
- " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n"
+ " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable(\n"
" internal_$identifier$_descriptor,\n"
" new java.lang.String[] { ",
- "identifier",
- UniqueFileScopeIdentifier(descriptor_));
+ "identifier", UniqueFileScopeIdentifier(descriptor_),
+ "ver", GeneratedCodeVersionSuffix());
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
@@ -254,11 +255,11 @@ void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
printer->Print(
"public interface $classname$OrBuilder$idend$ extends\n"
" $extra_interfaces$\n"
- " com.google.protobuf.GeneratedMessage.\n"
+ " com.google.protobuf.GeneratedMessage$ver$.\n"
" ExtendableMessageOrBuilder<$classname$> {\n",
"extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
"classname", descriptor_->name(),
- "idend", "");
+ "idend", "", "ver", GeneratedCodeVersionSuffix());
} else {
printer->Print(
"public interface $classname$OrBuilder$idend$ extends\n"
@@ -302,6 +303,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
variables["static"] = is_own_file ? " " : " static ";
variables["classname"] = descriptor_->name();
variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
+ variables["ver"] = GeneratedCodeVersionSuffix();
WriteMessageDocComment(printer, descriptor_);
MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
@@ -315,22 +317,25 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
printer->Annotate("classname", descriptor_);
printer->Print(
variables,
- " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
+ " com.google.protobuf.GeneratedMessage$ver$.ExtendableMessage<\n"
" $classname$> implements\n"
" $extra_interfaces$\n"
" $classname$OrBuilder {\n");
builder_type = strings::Substitute(
- "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>",
- name_resolver_->GetImmutableClassName(descriptor_));
+ "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
+ name_resolver_->GetImmutableClassName(descriptor_),
+ GeneratedCodeVersionSuffix());
} else {
printer->Print(variables,
"public $static$final class $classname$ extends\n");
printer->Annotate("classname", descriptor_);
printer->Print(variables,
- " com.google.protobuf.GeneratedMessage implements\n"
+ " com.google.protobuf.GeneratedMessage$ver$ implements\n"
" $extra_interfaces$\n"
" $classname$OrBuilder {\n");
- builder_type = "com.google.protobuf.GeneratedMessage.Builder<?>";
+ builder_type = strings::Substitute(
+ "com.google.protobuf.GeneratedMessage$0.Builder<?>",
+ GeneratedCodeVersionSuffix());
}
printer->Indent();
// Using builder_type, instead of Builder, prevents the Builder class from
@@ -581,16 +586,18 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) {
if (descriptor_->options().message_set_wire_format()) {
printer->Print(
- "com.google.protobuf.GeneratedMessage\n"
+ "com.google.protobuf.GeneratedMessage$ver$\n"
" .ExtendableMessage<$classname$>.ExtensionWriter\n"
" extensionWriter = newMessageSetExtensionWriter();\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "ver", GeneratedCodeVersionSuffix());
} else {
printer->Print(
- "com.google.protobuf.GeneratedMessage\n"
+ "com.google.protobuf.GeneratedMessage$ver$\n"
" .ExtendableMessage<$classname$>.ExtensionWriter\n"
" extensionWriter = newExtensionWriter();\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "ver", GeneratedCodeVersionSuffix());
}
}
@@ -694,43 +701,44 @@ GenerateParseFromMethods(io::Printer* printer) {
"}\n"
"public static $classname$ parseFrom(java.io.InputStream input)\n"
" throws java.io.IOException {\n"
- " return com.google.protobuf.GeneratedMessage\n"
+ " return com.google.protobuf.GeneratedMessage$ver$\n"
" .parseWithIOException(PARSER, input);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" java.io.InputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return com.google.protobuf.GeneratedMessage\n"
+ " return com.google.protobuf.GeneratedMessage$ver$\n"
" .parseWithIOException(PARSER, input, extensionRegistry);\n"
"}\n"
"public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
" throws java.io.IOException {\n"
- " return com.google.protobuf.GeneratedMessage\n"
+ " return com.google.protobuf.GeneratedMessage$ver$\n"
" .parseDelimitedWithIOException(PARSER, input);\n"
"}\n"
"public static $classname$ parseDelimitedFrom(\n"
" java.io.InputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return com.google.protobuf.GeneratedMessage\n"
+ " return com.google.protobuf.GeneratedMessage$ver$\n"
" .parseDelimitedWithIOException(PARSER, input, extensionRegistry);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.CodedInputStream input)\n"
" throws java.io.IOException {\n"
- " return com.google.protobuf.GeneratedMessage\n"
+ " return com.google.protobuf.GeneratedMessage$ver$\n"
" .parseWithIOException(PARSER, input);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.CodedInputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return com.google.protobuf.GeneratedMessage\n"
+ " return com.google.protobuf.GeneratedMessage$ver$\n"
" .parseWithIOException(PARSER, input, extensionRegistry);\n"
"}\n"
"\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "ver", GeneratedCodeVersionSuffix());
}
void ImmutableMessageGenerator::GenerateSerializeOneField(
@@ -769,10 +777,11 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
printer->Print(
"@java.lang.Override\n"
"protected Builder newBuilderForType(\n"
- " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
+ " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n"
" Builder builder = new Builder(parent);\n"
" return builder;\n"
- "}\n");
+ "}\n",
+ "ver", GeneratedCodeVersionSuffix());
MessageBuilderGenerator builderGenerator(descriptor_, context_);
builderGenerator.Generate(printer);
@@ -826,7 +835,7 @@ GenerateDescriptorMethods(io::Printer* printer) {
"}\n");
}
printer->Print(
- "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+ "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
" internalGetFieldAccessorTable() {\n"
" return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
" .ensureFieldAccessorsInitialized(\n"
@@ -835,7 +844,8 @@ GenerateDescriptorMethods(io::Printer* printer) {
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_),
"fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
- "identifier", UniqueFileScopeIdentifier(descriptor_));
+ "identifier", UniqueFileScopeIdentifier(descriptor_),
+ "ver", GeneratedCodeVersionSuffix());
}
// ===================================================================
diff --git a/src/google/protobuf/compiler/java/java_message_builder.cc b/src/google/protobuf/compiler/java/java_message_builder.cc
index b3e9e986..42154694 100644
--- a/src/google/protobuf/compiler/java/java_message_builder.cc
+++ b/src/google/protobuf/compiler/java/java_message_builder.cc
@@ -94,20 +94,22 @@ Generate(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) {
printer->Print(
"public static final class Builder extends\n"
- " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
+ " com.google.protobuf.GeneratedMessage$ver$.ExtendableBuilder<\n"
" $classname$, Builder> implements\n"
" $extra_interfaces$\n"
" $classname$OrBuilder {\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_),
- "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
+ "extra_interfaces", ExtraBuilderInterfaces(descriptor_),
+ "ver", GeneratedCodeVersionSuffix());
} else {
printer->Print(
"public static final class Builder extends\n"
- " com.google.protobuf.GeneratedMessage.Builder<Builder> implements\n"
+ " com.google.protobuf.GeneratedMessage$ver$.Builder<Builder> implements\n"
" $extra_interfaces$\n"
" $classname$OrBuilder {\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_),
- "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
+ "extra_interfaces", ExtraBuilderInterfaces(descriptor_),
+ "ver", GeneratedCodeVersionSuffix());
}
printer->Indent();
@@ -181,6 +183,18 @@ Generate(io::Printer* printer) {
" return this;\n"
"}\n"
"\n");
+ } else {
+ printer->Print(
+ "public final Builder setUnknownFields(\n"
+ " final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
+ " return super.setUnknownFields(unknownFields);\n"
+ "}\n"
+ "\n"
+ "public final Builder mergeUnknownFields(\n"
+ " final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
+ " return super.mergeUnknownFields(unknownFields);\n"
+ "}\n"
+ "\n");
}
printer->Print(
@@ -268,7 +282,7 @@ GenerateDescriptorMethods(io::Printer* printer) {
"}\n");
}
printer->Print(
- "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+ "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
" internalGetFieldAccessorTable() {\n"
" return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
" .ensureFieldAccessorsInitialized(\n"
@@ -277,7 +291,8 @@ GenerateDescriptorMethods(io::Printer* printer) {
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_),
"fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
- "identifier", UniqueFileScopeIdentifier(descriptor_));
+ "identifier", UniqueFileScopeIdentifier(descriptor_),
+ "ver", GeneratedCodeVersionSuffix());
}
// ===================================================================
@@ -294,15 +309,18 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
printer->Print(
"private Builder(\n"
- " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
+ " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n"
" super(parent);\n"
" maybeForceBuilderInitialization();\n"
"}\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "ver", GeneratedCodeVersionSuffix());
printer->Print(
"private void maybeForceBuilderInitialization() {\n"
- " if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n");
+ " if (com.google.protobuf.GeneratedMessage$ver$\n"
+ " .alwaysUseFieldBuilders) {\n",
+ "ver", GeneratedCodeVersionSuffix());
printer->Indent();
printer->Indent();
@@ -438,6 +456,62 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
+ printer->Print(
+ "public Builder clone() {\n"
+ " return (Builder) super.clone();\n"
+ "}\n"
+ "public Builder setField(\n"
+ " com.google.protobuf.Descriptors.FieldDescriptor field,\n"
+ " Object value) {\n"
+ " return (Builder) super.setField(field, value);\n"
+ "}\n"
+ "public Builder clearField(\n"
+ " com.google.protobuf.Descriptors.FieldDescriptor field) {\n"
+ " return (Builder) super.clearField(field);\n"
+ "}\n"
+ "public Builder clearOneof(\n"
+ " com.google.protobuf.Descriptors.OneofDescriptor oneof) {\n"
+ " return (Builder) super.clearOneof(oneof);\n"
+ "}\n"
+ "public Builder setRepeatedField(\n"
+ " com.google.protobuf.Descriptors.FieldDescriptor field,\n"
+ " int index, Object value) {\n"
+ " return (Builder) super.setRepeatedField(field, index, value);\n"
+ "}\n"
+ "public Builder addRepeatedField(\n"
+ " com.google.protobuf.Descriptors.FieldDescriptor field,\n"
+ " Object value) {\n"
+ " return (Builder) super.addRepeatedField(field, value);\n"
+ "}\n");
+
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "public <Type> Builder setExtension(\n"
+ " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+ " $classname$, Type> extension,\n"
+ " Type value) {\n"
+ " return (Builder) super.setExtension(extension, value);\n"
+ "}\n"
+ "public <Type> Builder setExtension(\n"
+ " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+ " $classname$, java.util.List<Type>> extension,\n"
+ " int index, Type value) {\n"
+ " return (Builder) super.setExtension(extension, index, value);\n"
+ "}\n"
+ "public <Type> Builder addExtension(\n"
+ " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+ " $classname$, java.util.List<Type>> extension,\n"
+ " Type value) {\n"
+ " return (Builder) super.addExtension(extension, value);\n"
+ "}\n"
+ "public <Type> Builder clearExtension(\n"
+ " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+ " $classname$, ?> extension) {\n"
+ " return (Builder) super.clearExtension(extension);\n"
+ "}\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ }
+
// -----------------------------------------------------------------
if (context_->HasGeneratedMethods(descriptor_)) {
@@ -522,6 +596,7 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
" return this;\n"
"}\n"
"\n");
+
}
}
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index cc627b5a..c9865dda 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -1203,7 +1203,7 @@ GenerateMergingCode(io::Printer* printer) const {
" $name$_ = other.$name$_;\n"
" $clear_mutable_bit_builder$;\n"
" $name$Builder_ = \n"
- " com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?\n"
+ " com.google.protobuf.GeneratedMessage$ver$.alwaysUseFieldBuilders ?\n"
" get$capitalized_name$FieldBuilder() : null;\n"
" } else {\n"
" $name$Builder_.addAllMessages(other.$name$_);\n"
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
index e1e5496a..ff1865b1 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -79,9 +79,11 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
" throw new NullPointerException();\n"
" }\n";
(*variables)["writeString"] =
- "com.google.protobuf.GeneratedMessage.writeString";
+ "com.google.protobuf.GeneratedMessage" + GeneratedCodeVersionSuffix() +
+ ".writeString";
(*variables)["computeStringSize"] =
- "com.google.protobuf.GeneratedMessage.computeStringSize";
+ "com.google.protobuf.GeneratedMessage" + GeneratedCodeVersionSuffix() +
+ ".computeStringSize";
// TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
// by the proto compiler
diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc
index 8a2633d7..58c77d00 100755
--- a/src/google/protobuf/compiler/js/js_generator.cc
+++ b/src/google/protobuf/compiler/js/js_generator.cc
@@ -768,7 +768,6 @@ string MaybeNumberString(const FieldDescriptor* field, const string& orig) {
}
string JSFieldDefault(const FieldDescriptor* field) {
- assert(field->has_default_value());
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
return MaybeNumberString(
@@ -943,7 +942,7 @@ string JSFieldTypeAnnotation(const GeneratorOptions& options,
}
if (field->is_optional() && is_primitive &&
- (!field->has_default_value() || force_optional) && !force_present) {
+ force_optional && !force_present) {
jstype += "?";
} else if (field->is_required() && !is_primitive && !force_optional) {
jstype = "!" + jstype;
@@ -1258,6 +1257,10 @@ string GetPivot(const Descriptor* desc) {
// Returns true for fields that represent "null" as distinct from the default
// value. See http://go/proto3#heading=h.kozewqqcqhuz for more information.
bool HasFieldPresence(const FieldDescriptor* field) {
+ if (field->is_repeated()) {
+ return false;
+ }
+
return
(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ||
(field->containing_oneof() != NULL) ||
@@ -2031,9 +2034,8 @@ void Generator::GenerateClassFieldToObject(const GeneratorOptions& options,
"getter", JSGetterName(options, field, BYTES_B64));
} else {
if (field->has_default_value()) {
- printer->Print("jspb.Message.getField(msg, $index$) == null ? "
- "$defaultValue$ : ",
- "index", JSFieldIndex(field),
+ printer->Print("!msg.has$name$() ? $defaultValue$ : ",
+ "name", JSGetterName(options, field),
"defaultValue", JSFieldDefault(field));
}
if (field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT ||
@@ -2253,25 +2255,6 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
" null");
}
- if (options.binary) {
- printer->Print(",\n"
- " $keyWriterFn$,\n"
- " $keyReaderFn$,\n"
- " $valueWriterFn$,\n"
- " $valueReaderFn$",
- "keyWriterFn", JSBinaryWriterMethodName(options, key_field),
- "keyReaderFn", JSBinaryReaderMethodName(options, key_field),
- "valueWriterFn", JSBinaryWriterMethodName(options, value_field),
- "valueReaderFn", JSBinaryReaderMethodName(options, value_field));
-
- if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
- printer->Print(",\n"
- " $messageType$.serializeBinaryToWriter,\n"
- " $messageType$.deserializeBinaryFromReader",
- "messageType", GetPath(options, value_field->message_type()));
- }
- }
-
printer->Print(
"));\n");
@@ -2407,10 +2390,9 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
"index", JSFieldIndex(field),
"default", Proto3PrimitiveFieldDefault(field));
} else {
- if (field->has_default_value()) {
- printer->Print("jspb.Message.getField(this, $index$) == null ? "
- "$defaultValue$ : ",
- "index", JSFieldIndex(field),
+ if (!field->is_repeated()) {
+ printer->Print("!this.has$name$() ? $defaultValue$ : ",
+ "name", JSGetterName(options, field),
"defaultValue", JSFieldDefault(field));
}
if (field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT ||
@@ -2419,10 +2401,6 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
printer->Print("jspb.Message.getRepeatedFloatingPointField("
"this, $index$)",
"index", JSFieldIndex(field));
- } else if (field->is_optional() && !field->has_default_value()) {
- printer->Print("jspb.Message.getOptionalFloatingPointField("
- "this, $index$)",
- "index", JSFieldIndex(field));
} else {
// Convert "NaN" to NaN.
printer->Print("+jspb.Message.getField(this, $index$)",
@@ -2498,7 +2476,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
"returndoc", JSReturnDoc(options, field));
}
- if (HasFieldPresence(field)) {
+ if (HasFieldPresence(field) || field->is_repeated()) {
printer->Print(
"$class$.prototype.clear$name$ = function() {\n"
" jspb.Message.set$oneoftag$Field(this, $index$$oneofgroup$, ",
@@ -2517,6 +2495,22 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
"returnvalue", JSReturnClause(field));
}
}
+
+ if (HasFieldPresence(field)) {
+ printer->Print(
+ "/**\n"
+ " * Returns whether this field is set.\n"
+ " * @return{!boolean}\n"
+ " */\n"
+ "$class$.prototype.has$name$ = function() {\n"
+ " return jspb.Message.getField(this, $index$) != null;\n"
+ "};\n"
+ "\n"
+ "\n",
+ "class", GetPath(options, field->containing_type()),
+ "name", JSGetterName(options, field),
+ "index", JSFieldIndex(field));
+ }
}
void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
@@ -2543,6 +2537,29 @@ void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
"$class$.extensions = {};\n"
"\n",
"class", GetPath(options, desc));
+
+ if (options.binary) {
+ printer->Print(
+ "\n"
+ "/**\n"
+ " * The extensions registered with this message class. This is a "
+ "map of\n"
+ " * extension field number to fieldInfo object.\n"
+ " *\n"
+ " * For example:\n"
+ " * { 123: {fieldIndex: 123, fieldName: {my_field_name: 0}, "
+ "ctor: proto.example.MyMessage} }\n"
+ " *\n"
+ " * fieldName contains the JsCompiler renamed field name property "
+ "so that it\n"
+ " * works in OPTIMIZED mode.\n"
+ " *\n"
+ " * @type {!Object.<number, jspb.ExtensionFieldInfo>}\n"
+ " */\n"
+ "$class$.extensionsBinary = {};\n"
+ "\n",
+ "class", GetPath(options, desc));
+ }
}
}
@@ -2590,7 +2607,7 @@ void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options,
" default:\n");
if (IsExtendable(desc)) {
printer->Print(
- " jspb.Message.readBinaryExtension(msg, reader, $extobj$,\n"
+ " jspb.Message.readBinaryExtension(msg, reader, $extobj$Binary,\n"
" $class$.prototype.getExtension,\n"
" $class$.prototype.setExtension);\n"
" break;\n",
@@ -2620,10 +2637,25 @@ void Generator::GenerateClassDeserializeBinaryField(
"num", SimpleItoa(field->number()));
if (field->is_map()) {
+ const FieldDescriptor* key_field = MapFieldKey(field);
+ const FieldDescriptor* value_field = MapFieldValue(field);
printer->Print(
" var value = msg.get$name$();\n"
- " reader.readMessage(value, jspb.Map.deserializeBinary);\n",
+ " reader.readMessage(value, function(message, reader) {\n",
"name", JSGetterName(options, field));
+
+ printer->Print(" jspb.Map.deserializeBinary(message, reader, "
+ "$keyReaderFn$, $valueReaderFn$",
+ "keyReaderFn", JSBinaryReaderMethodName(options, key_field),
+ "valueReaderFn", JSBinaryReaderMethodName(options, value_field));
+
+ if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+ printer->Print(", $messageType$.deserializeBinaryFromReader",
+ "messageType", GetPath(options, value_field->message_type()));
+ }
+
+ printer->Print(");\n");
+ printer->Print(" });\n");
} else {
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
printer->Print(
@@ -2709,8 +2741,8 @@ void Generator::GenerateClassSerializeBinary(const GeneratorOptions& options,
if (IsExtendable(desc)) {
printer->Print(
- " jspb.Message.serializeBinaryExtensions(this, writer, $extobj$,\n"
- " $class$.prototype.getExtension);\n",
+ " jspb.Message.serializeBinaryExtensions(this, writer,\n"
+ " $extobj$Binary, $class$.prototype.getExtension);\n",
"extobj", JSExtensionsObjectName(options, desc->file(), desc),
"class", GetPath(options, desc));
}
@@ -2725,11 +2757,18 @@ void Generator::GenerateClassSerializeBinaryField(
const GeneratorOptions& options,
io::Printer* printer,
const FieldDescriptor* field) const {
- printer->Print(
- " f = this.get$name$($nolazy$);\n",
- "name", JSGetterName(options, field, BYTES_U8),
- // No lazy creation for maps containers -- fastpath the empty case.
- "nolazy", (field->is_map()) ? "true" : "");
+ if (HasFieldPresence(field) &&
+ field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+ printer->Print(
+ " f = jspb.Message.getField(this, $index$);\n",
+ "index", JSFieldIndex(field));
+ } else {
+ printer->Print(
+ " f = this.get$name$($nolazy$);\n",
+ "name", JSGetterName(options, field, BYTES_U8),
+ // No lazy creation for maps containers -- fastpath the empty case.
+ "nolazy", (field->is_map()) ? "true" : "");
+ }
// Print an `if (condition)` statement that evaluates to true if the field
@@ -2782,9 +2821,21 @@ void Generator::GenerateClassSerializeBinaryField(
// Write the field on the wire.
if (field->is_map()) {
+ const FieldDescriptor* key_field = MapFieldKey(field);
+ const FieldDescriptor* value_field = MapFieldValue(field);
printer->Print(
- " f.serializeBinary($index$, writer);\n",
- "index", SimpleItoa(field->number()));
+ " f.serializeBinary($index$, writer, "
+ "$keyWriterFn$, $valueWriterFn$",
+ "index", SimpleItoa(field->number()),
+ "keyWriterFn", JSBinaryWriterMethodName(options, key_field),
+ "valueWriterFn", JSBinaryWriterMethodName(options, value_field));
+
+ if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+ printer->Print(", $messageType$.serializeBinaryToWriter",
+ "messageType", GetPath(options, value_field->message_type()));
+ }
+
+ printer->Print(");\n");
} else {
printer->Print(
" writer.write$method$(\n"
@@ -2866,7 +2917,7 @@ void Generator::GenerateExtension(const GeneratorOptions& options,
" /** @type {?function((boolean|undefined),!jspb.Message=): "
"!Object} */ (\n"
" $toObject$),\n"
- " $repeated$",
+ " $repeated$);\n",
"index", SimpleItoa(field->number()),
"name", JSObjectFieldName(options, field),
"ctor", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ?
@@ -2878,12 +2929,18 @@ void Generator::GenerateExtension(const GeneratorOptions& options,
if (options.binary) {
printer->Print(
- ",\n"
+ "\n"
+ "$extendName$Binary[$index$] = new jspb.ExtensionFieldBinaryInfo(\n"
+ " $class$.$name$,\n"
" $binaryReaderFn$,\n"
" $binaryWriterFn$,\n"
" $binaryMessageSerializeFn$,\n"
- " $binaryMessageDeserializeFn$,\n"
- " $isPacked$);\n",
+ " $binaryMessageDeserializeFn$,\n",
+ "extendName", JSExtensionsObjectName(options, field->file(),
+ field->containing_type()),
+ "index", SimpleItoa(field->number()),
+ "class", extension_scope,
+ "name", JSObjectFieldName(options, field),
"binaryReaderFn", JSBinaryReaderMethodName(options, field),
"binaryWriterFn", JSBinaryWriterMethodName(options, field),
"binaryMessageSerializeFn",
@@ -2893,10 +2950,11 @@ void Generator::GenerateExtension(const GeneratorOptions& options,
"binaryMessageDeserializeFn",
(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ?
(SubmessageTypeRef(options, field) +
- ".deserializeBinaryFromReader") : "null",
+ ".deserializeBinaryFromReader") : "null");
+
+ printer->Print(
+ " $isPacked$);\n",
"isPacked", (field->is_packed() ? "true" : "false"));
- } else {
- printer->Print(");\n");
}
printer->Print(
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
index e76f8e99..34e17823 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
@@ -62,7 +62,7 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) {
string enum_comments;
SourceLocation location;
if (descriptor_->GetSourceLocation(&location)) {
- enum_comments = BuildCommentsString(location);
+ enum_comments = BuildCommentsString(location, true);
} else {
enum_comments = "";
}
@@ -81,16 +81,18 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) {
if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
// Include the unknown value.
printer->Print(
- "/// Value used if any message's field encounters a value that is not defined\n"
- "/// by this enum. The message will also have C functions to get/set the rawValue\n"
- "/// of the field.\n"
+ "/**\n"
+ " * Value used if any message's field encounters a value that is not defined\n"
+ " * by this enum. The message will also have C functions to get/set the rawValue\n"
+ " * of the field.\n"
+ " **/\n"
"$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n",
"name", name_);
}
for (int i = 0; i < all_values_.size(); i++) {
SourceLocation location;
if (all_values_[i]->GetSourceLocation(&location)) {
- string comments = BuildCommentsString(location).c_str();
+ string comments = BuildCommentsString(location, true).c_str();
if (comments.length() > 0) {
if (i > 0) {
printer->Print("\n");
@@ -111,8 +113,10 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) {
"\n"
"GPBEnumDescriptor *$name$_EnumDescriptor(void);\n"
"\n"
- "/// Checks to see if the given value is defined by the enum or was not known at\n"
- "/// the time this source was generated.\n"
+ "/**\n"
+ " * Checks to see if the given value is defined by the enum or was not known at\n"
+ " * the time this source was generated.\n"
+ " **/\n"
"BOOL $name$_IsValidValue(int32_t value);\n"
"\n",
"name", name_);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
index b63bc0de..7a774a09 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
@@ -83,12 +83,16 @@ void EnumFieldGenerator::GenerateCFunctionDeclarations(
printer->Print(
variables_,
- "/// Fetches the raw value of a @c $owning_message_class$'s @c $name$ property, even\n"
- "/// if the value was not defined by the enum at the time the code was generated.\n"
+ "/**\n"
+ " * Fetches the raw value of a @c $owning_message_class$'s @c $name$ property, even\n"
+ " * if the value was not defined by the enum at the time the code was generated.\n"
+ " **/\n"
"int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message);\n"
- "/// Sets the raw value of an @c $owning_message_class$'s @c $name$ property, allowing\n"
- "/// it to be set to a value that was not defined by the enum at the time the code\n"
- "/// was generated.\n"
+ "/**\n"
+ " * Sets the raw value of an @c $owning_message_class$'s @c $name$ property, allowing\n"
+ " * it to be set to a value that was not defined by the enum at the time the code\n"
+ " * was generated.\n"
+ " **/\n"
"void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value);\n"
"\n");
}
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
index 3f7ab9d3..d0de1eca 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
@@ -63,7 +63,7 @@ void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) {
vars["method_name"] = method_name_;
SourceLocation location;
if (descriptor_->GetSourceLocation(&location)) {
- vars["comments"] = BuildCommentsString(location);
+ vars["comments"] = BuildCommentsString(location, true);
} else {
vars["comments"] = "";
}
@@ -85,7 +85,7 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization(
if (descriptor_->containing_type()->options().message_set_wire_format())
options.push_back("GPBExtensionSetWireFormat");
- vars["options"] = BuildFlagsString(options);
+ vars["options"] = BuildFlagsString(FLAGTYPE_EXTENSION, options);
ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
string singular_type;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
index 812b4a1c..527b7c0c 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
@@ -64,7 +64,7 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
SourceLocation location;
if (descriptor->GetSourceLocation(&location)) {
- (*variables)["comments"] = BuildCommentsString(location);
+ (*variables)["comments"] = BuildCommentsString(location, true);
} else {
(*variables)["comments"] = "\n";
}
@@ -93,7 +93,7 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
field_flags.push_back("GPBFieldHasEnumDescriptor");
}
- (*variables)["fieldflags"] = BuildFlagsString(field_flags);
+ (*variables)["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags);
(*variables)["default"] = DefaultValue(descriptor);
(*variables)["default_name"] = GPBGenericValueFieldName(descriptor);
@@ -335,7 +335,7 @@ void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
if (WantsHasProperty()) {
printer->Print(
variables_,
- "/// Test to see if @c $name$ has been set.\n"
+ "/** Test to see if @c $name$ has been set. */\n"
"@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
}
if (IsInitName(variables_.find("name")->second)) {
@@ -387,7 +387,7 @@ void RepeatedFieldGenerator::GeneratePropertyDeclaration(
"$comments$"
"$array_comment$"
"@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n"
- "/// The number of items in @c $name$ without causing the array to be created.\n"
+ "/** The number of items in @c $name$ without causing the array to be created. */\n"
"@property(nonatomic, readonly) NSUInteger $name$_Count$deprecated_attribute$;\n");
if (IsInitName(variables_.find("name")->second)) {
// If property name starts with init we need to annotate it to get past ARC.
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
index cf8c34e1..878a3743 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
@@ -37,6 +37,7 @@
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/stl_util.h>
#include <google/protobuf/stubs/strutil.h>
+#include <algorithm> // std::find()
#include <iostream>
#include <sstream>
@@ -45,218 +46,122 @@
namespace google {
namespace protobuf {
-
-// This is also found in GPBBootstrap.h, and needs to be kept in sync. It
-// is the version check done to ensure generated code works with the current
-// runtime being used.
-const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30001;
-
namespace compiler {
namespace objectivec {
namespace {
-class ImportWriter {
- public:
- ImportWriter(const Options& options)
- : options_(options),
- need_to_parse_mapping_file_(true) {}
-
- void AddFile(const FileGenerator* file);
- void Print(io::Printer *printer) const;
-
- private:
- class ProtoFrameworkCollector : public LineConsumer {
- public:
- ProtoFrameworkCollector(map<string, string>* inout_proto_file_to_framework_name)
- : map_(inout_proto_file_to_framework_name) {}
-
- virtual bool ConsumeLine(const StringPiece& line, string* out_error);
-
- private:
- map<string, string>* map_;
- };
-
- void ParseFrameworkMappings();
-
- const Options options_;
- map<string, string> proto_file_to_framework_name_;
- bool need_to_parse_mapping_file_;
-
- vector<string> protobuf_framework_imports_;
- vector<string> protobuf_non_framework_imports_;
- vector<string> other_framework_imports_;
- vector<string> other_imports_;
-};
+// This is also found in GPBBootstrap.h, and needs to be kept in sync. It
+// is the version check done to ensure generated code works with the current
+// runtime being used.
+const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30002;
-void ImportWriter::AddFile(const FileGenerator* file) {
- const FileDescriptor* file_descriptor = file->Descriptor();
- const string extension(".pbobjc.h");
+const char* kHeaderExtension = ".pbobjc.h";
- if (IsProtobufLibraryBundledProtoFile(file_descriptor)) {
- protobuf_framework_imports_.push_back(
- FilePathBasename(file_descriptor) + extension);
- protobuf_non_framework_imports_.push_back(file->Path() + extension);
- return;
+// Checks if a message contains any extension definitions (on the message or
+// a nested message under it).
+bool MessageContainsExtensions(const Descriptor* message) {
+ if (message->extension_count() > 0) {
+ return true;
}
-
- // Lazy parse any mappings.
- if (need_to_parse_mapping_file_) {
- ParseFrameworkMappings();
+ for (int i = 0; i < message->nested_type_count(); i++) {
+ if (MessageContainsExtensions(message->nested_type(i))) {
+ return true;
+ }
}
+ return false;
+}
- map<string, string>::iterator proto_lookup =
- proto_file_to_framework_name_.find(file_descriptor->name());
- if (proto_lookup != proto_file_to_framework_name_.end()) {
- other_framework_imports_.push_back(
- proto_lookup->second + "/" +
- FilePathBasename(file_descriptor) + extension);
- return;
+// Checks if the file contains any extensions definitions (at the root or
+// nested under a message).
+bool FileContainsExtensions(const FileDescriptor* file) {
+ if (file->extension_count() > 0) {
+ return true;
}
-
- if (!options_.generate_for_named_framework.empty()) {
- other_framework_imports_.push_back(
- options_.generate_for_named_framework + "/" +
- FilePathBasename(file_descriptor) + extension);
- return;
+ for (int i = 0; i < file->message_type_count(); i++) {
+ if (MessageContainsExtensions(file->message_type(i))) {
+ return true;
+ }
}
-
- other_imports_.push_back(file->Path() + extension);
+ return false;
}
-void ImportWriter::Print(io::Printer* printer) const {
- assert(protobuf_non_framework_imports_.size() ==
- protobuf_framework_imports_.size());
-
- bool add_blank_line = false;
-
- if (protobuf_framework_imports_.size() > 0) {
- const string framework_name(ProtobufLibraryFrameworkName);
- const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name));
-
- printer->Print(
- "#if $cpp_symbol$\n",
- "cpp_symbol", cpp_symbol);
- for (vector<string>::const_iterator iter = protobuf_framework_imports_.begin();
- iter != protobuf_framework_imports_.end(); ++iter) {
- printer->Print(
- " #import <$framework_name$/$header$>\n",
- "framework_name", framework_name,
- "header", *iter);
- }
- printer->Print(
- "#else\n");
- for (vector<string>::const_iterator iter = protobuf_non_framework_imports_.begin();
- iter != protobuf_non_framework_imports_.end(); ++iter) {
- printer->Print(
- " #import \"$header$\"\n",
- "header", *iter);
- }
- printer->Print(
- "#endif\n");
-
- add_blank_line = true;
+// Helper for CollectMinimalFileDepsContainingExtensionsWorker that marks all
+// deps as visited and prunes them from the needed files list.
+void PruneFileAndDepsMarkingAsVisited(
+ const FileDescriptor* file,
+ vector<const FileDescriptor*>* files,
+ set<const FileDescriptor*>* files_visited) {
+ vector<const FileDescriptor*>::iterator iter =
+ std::find(files->begin(), files->end(), file);
+ if (iter != files->end()) {
+ files->erase(iter);
}
+ files_visited->insert(file);
+ for (int i = 0; i < file->dependency_count(); i++) {
+ PruneFileAndDepsMarkingAsVisited(file->dependency(i), files, files_visited);
+ }
+}
- if (other_framework_imports_.size() > 0) {
- if (add_blank_line) {
- printer->Print("\n");
- }
-
- for (vector<string>::const_iterator iter = other_framework_imports_.begin();
- iter != other_framework_imports_.end(); ++iter) {
- printer->Print(
- " #import <$header$>\n",
- "header", *iter);
- }
-
- add_blank_line = true;
+// Helper for CollectMinimalFileDepsContainingExtensions.
+void CollectMinimalFileDepsContainingExtensionsWorker(
+ const FileDescriptor* file,
+ vector<const FileDescriptor*>* files,
+ set<const FileDescriptor*>* files_visited) {
+ if (files_visited->find(file) != files_visited->end()) {
+ return;
}
+ files_visited->insert(file);
- if (other_imports_.size() > 0) {
- if (add_blank_line) {
- printer->Print("\n");
+ if (FileContainsExtensions(file)) {
+ files->push_back(file);
+ for (int i = 0; i < file->dependency_count(); i++) {
+ const FileDescriptor* dep = file->dependency(i);
+ PruneFileAndDepsMarkingAsVisited(dep, files, files_visited);
}
-
- for (vector<string>::const_iterator iter = other_imports_.begin();
- iter != other_imports_.end(); ++iter) {
- printer->Print(
- " #import \"$header$\"\n",
- "header", *iter);
+ } else {
+ for (int i = 0; i < file->dependency_count(); i++) {
+ const FileDescriptor* dep = file->dependency(i);
+ CollectMinimalFileDepsContainingExtensionsWorker(dep, files,
+ files_visited);
}
}
}
-void ImportWriter::ParseFrameworkMappings() {
- need_to_parse_mapping_file_ = false;
- if (options_.named_framework_to_proto_path_mappings_path.empty()) {
- return; // Nothing to do.
- }
-
- ProtoFrameworkCollector collector(&proto_file_to_framework_name_);
- string parse_error;
- if (!ParseSimpleFile(options_.named_framework_to_proto_path_mappings_path,
- &collector, &parse_error)) {
- cerr << "error parsing " << options_.named_framework_to_proto_path_mappings_path
- << " : " << parse_error << endl;
- cerr.flush();
+// Collect the deps of the given file that contain extensions. This can be used to
+// create the chain of roots that need to be wired together.
+//
+// NOTE: If any changes are made to this and the supporting functions, you will
+// need to manually validate what the generated code is for the test files:
+// objectivec/Tests/unittest_extension_chain_*.proto
+// There are comments about what the expected code should be line and limited
+// testing objectivec/Tests/GPBUnittestProtos2.m around compilation (#imports
+// specifically).
+void CollectMinimalFileDepsContainingExtensions(
+ const FileDescriptor* file,
+ vector<const FileDescriptor*>* files) {
+ set<const FileDescriptor*> files_visited;
+ for (int i = 0; i < file->dependency_count(); i++) {
+ const FileDescriptor* dep = file->dependency(i);
+ CollectMinimalFileDepsContainingExtensionsWorker(dep, files,
+ &files_visited);
}
}
-bool ImportWriter::ProtoFrameworkCollector::ConsumeLine(
- const StringPiece& line, string* out_error) {
- int offset = line.find(':');
- if (offset == StringPiece::npos) {
- *out_error =
- string("Framework/proto file mapping line without colon sign: '") +
- line.ToString() + "'.";
- return false;
- }
- StringPiece framework_name(line, 0, offset);
- StringPiece proto_file_list(line, offset + 1, line.length() - offset - 1);
- StringPieceTrimWhitespace(&framework_name);
-
- int start = 0;
- while (start < proto_file_list.length()) {
- offset = proto_file_list.find(',', start);
- if (offset == StringPiece::npos) {
- offset = proto_file_list.length();
- }
-
- StringPiece proto_file(proto_file_list, start, offset);
- StringPieceTrimWhitespace(&proto_file);
- if (proto_file.size() != 0) {
- map<string, string>::iterator existing_entry =
- map_->find(proto_file.ToString());
- if (existing_entry != map_->end()) {
- cerr << "warning: duplicate proto file reference, replacing framework entry for '"
- << proto_file.ToString() << "' with '" << framework_name.ToString()
- << "' (was '" << existing_entry->second << "')." << endl;
- cerr.flush();
- }
-
- if (proto_file.find(' ') != StringPiece::npos) {
- cerr << "note: framework mapping file had a proto file with a space in, hopefully that isn't a missing comma: '"
- << proto_file.ToString() << "'" << endl;
- cerr.flush();
- }
-
- (*map_)[proto_file.ToString()] = framework_name.ToString();
+bool IsDirectDependency(const FileDescriptor* dep, const FileDescriptor* file) {
+ for (int i = 0; i < file->dependency_count(); i++) {
+ if (dep == file->dependency(i)) {
+ return true;
}
-
- start = offset + 1;
}
-
- return true;
+ return false;
}
} // namespace
-
FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options)
: file_(file),
root_class_name_(FileClassName(file)),
- is_public_dep_(false),
options_(options) {
for (int i = 0; i < file_->enum_type_count(); i++) {
EnumGenerator *generator = new EnumGenerator(file_->enum_type(i));
@@ -275,8 +180,6 @@ FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options)
}
FileGenerator::~FileGenerator() {
- STLDeleteContainerPointers(dependency_generators_.begin(),
- dependency_generators_.end());
STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end());
STLDeleteContainerPointers(message_generators_.begin(),
message_generators_.end());
@@ -299,14 +202,12 @@ void FileGenerator::GenerateHeader(io::Printer *printer) {
// #import any headers for "public imports" in the proto file.
{
- ImportWriter import_writer(options_);
- const vector<FileGenerator *> &dependency_generators = DependencyGenerators();
- for (vector<FileGenerator *>::const_iterator iter =
- dependency_generators.begin();
- iter != dependency_generators.end(); ++iter) {
- if ((*iter)->IsPublicDependency()) {
- import_writer.AddFile(*iter);
- }
+ ImportWriter import_writer(
+ options_.generate_for_named_framework,
+ options_.named_framework_to_proto_path_mappings_path);
+ const string header_extension(kHeaderExtension);
+ for (int i = 0; i < file_->public_dependency_count(); i++) {
+ import_writer.AddFile(file_->public_dependency(i), header_extension);
}
import_writer.Print(printer);
}
@@ -357,14 +258,16 @@ void FileGenerator::GenerateHeader(io::Printer *printer) {
printer->Print(
"#pragma mark - $root_class_name$\n"
"\n"
- "/// Exposes the extension registry for this file.\n"
- "///\n"
- "/// The base class provides:\n"
- "/// @code\n"
- "/// + (GPBExtensionRegistry *)extensionRegistry;\n"
- "/// @endcode\n"
- "/// which is a @c GPBExtensionRegistry that includes all the extensions defined by\n"
- "/// this file and all files that it depends on.\n"
+ "/**\n"
+ " * Exposes the extension registry for this file.\n"
+ " *\n"
+ " * The base class provides:\n"
+ " * @code\n"
+ " * + (GPBExtensionRegistry *)extensionRegistry;\n"
+ " * @endcode\n"
+ " * which is a @c GPBExtensionRegistry that includes all the extensions defined by\n"
+ " * this file and all files that it depends on.\n"
+ " **/\n"
"@interface $root_class_name$ : GPBRootObject\n"
"@end\n"
"\n",
@@ -404,21 +307,41 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
// #import the runtime support.
PrintFileRuntimePreamble(printer, "GPBProtocolBuffers_RuntimeSupport.h");
+ vector<const FileDescriptor*> deps_with_extensions;
+ CollectMinimalFileDepsContainingExtensions(file_, &deps_with_extensions);
+
{
- ImportWriter import_writer(options_);
+ ImportWriter import_writer(
+ options_.generate_for_named_framework,
+ options_.named_framework_to_proto_path_mappings_path);
+ const string header_extension(kHeaderExtension);
// #import the header for this proto file.
- import_writer.AddFile(this);
+ import_writer.AddFile(file_, header_extension);
// #import the headers for anything that a plain dependency of this proto
// file (that means they were just an include, not a "public" include).
- const vector<FileGenerator *> &dependency_generators =
- DependencyGenerators();
- for (vector<FileGenerator *>::const_iterator iter =
- dependency_generators.begin();
- iter != dependency_generators.end(); ++iter) {
- if (!(*iter)->IsPublicDependency()) {
- import_writer.AddFile(*iter);
+ set<string> public_import_names;
+ for (int i = 0; i < file_->public_dependency_count(); i++) {
+ public_import_names.insert(file_->public_dependency(i)->name());
+ }
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ const FileDescriptor *dep = file_->dependency(i);
+ bool public_import = (public_import_names.count(dep->name()) != 0);
+ if (!public_import) {
+ import_writer.AddFile(dep, header_extension);
+ }
+ }
+
+ // If any indirect dependency provided extensions, it needs to be directly
+ // imported so it can get merged into the root's extensions registry.
+ // See the Note by CollectMinimalFileDepsContainingExtensions before
+ // changing this.
+ for (vector<const FileDescriptor *>::iterator iter =
+ deps_with_extensions.begin();
+ iter != deps_with_extensions.end(); ++iter) {
+ if (!IsDirectDependency(*iter, file_)) {
+ import_writer.AddFile(*iter, header_extension);
}
}
@@ -458,29 +381,11 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
"@implementation $root_class_name$\n\n",
"root_class_name", root_class_name_);
- // Generate the extension initialization structures for the top level and
- // any nested messages.
- ostringstream extensions_stringstream;
- if (file_->extension_count() + file_->message_type_count() > 0) {
- io::OstreamOutputStream extensions_outputstream(&extensions_stringstream);
- io::Printer extensions_printer(&extensions_outputstream, '$');
- for (vector<ExtensionGenerator *>::iterator iter =
- extension_generators_.begin();
- iter != extension_generators_.end(); ++iter) {
- (*iter)->GenerateStaticVariablesInitialization(&extensions_printer);
- }
- for (vector<MessageGenerator *>::iterator iter =
- message_generators_.begin();
- iter != message_generators_.end(); ++iter) {
- (*iter)->GenerateStaticVariablesInitialization(&extensions_printer);
- }
- extensions_stringstream.flush();
- }
+ const bool file_contains_extensions = FileContainsExtensions(file_);
// If there were any extensions or this file has any dependencies, output
// a registry to override to create the file specific registry.
- const string& extensions_str = extensions_stringstream.str();
- if (extensions_str.length() > 0 || file_->dependency_count() > 0) {
+ if (file_contains_extensions || !deps_with_extensions.empty()) {
printer->Print(
"+ (GPBExtensionRegistry*)extensionRegistry {\n"
" // This is called by +initialize so there is no need to worry\n"
@@ -493,11 +398,20 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
printer->Indent();
printer->Indent();
- if (extensions_str.length() > 0) {
+ if (file_contains_extensions) {
printer->Print(
"static GPBExtensionDescription descriptions[] = {\n");
printer->Indent();
- printer->Print(extensions_str.c_str());
+ for (vector<ExtensionGenerator *>::iterator iter =
+ extension_generators_.begin();
+ iter != extension_generators_.end(); ++iter) {
+ (*iter)->GenerateStaticVariablesInitialization(printer);
+ }
+ for (vector<MessageGenerator *>::iterator iter =
+ message_generators_.begin();
+ iter != message_generators_.end(); ++iter) {
+ (*iter)->GenerateStaticVariablesInitialization(printer);
+ }
printer->Outdent();
printer->Print(
"};\n"
@@ -510,14 +424,21 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
"}\n");
}
- const vector<FileGenerator *> &dependency_generators =
- DependencyGenerators();
- for (vector<FileGenerator *>::const_iterator iter =
- dependency_generators.begin();
- iter != dependency_generators.end(); ++iter) {
+ if (deps_with_extensions.empty()) {
printer->Print(
- "[registry addExtensions:[$dependency$ extensionRegistry]];\n",
- "dependency", (*iter)->RootClassName());
+ "// None of the imports (direct or indirect) defined extensions, so no need to add\n"
+ "// them to this registry.\n");
+ } else {
+ printer->Print(
+ "// Merge in the imports (direct or indirect) that defined extensions.\n");
+ for (vector<const FileDescriptor *>::iterator iter =
+ deps_with_extensions.begin();
+ iter != deps_with_extensions.end(); ++iter) {
+ const string root_class_name(FileClassName((*iter)));
+ printer->Print(
+ "[registry addExtensions:[$dependency$ extensionRegistry]];\n",
+ "dependency", root_class_name);
+ }
}
printer->Outdent();
@@ -526,27 +447,39 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
printer->Print(
" }\n"
" return registry;\n"
- "}\n"
- "\n");
+ "}\n");
+ } else {
+ if (file_->dependency_count() > 0) {
+ printer->Print(
+ "// No extensions in the file and none of the imports (direct or indirect)\n"
+ "// defined extensions, so no need to generate +extensionRegistry.\n");
+ } else {
+ printer->Print(
+ "// No extensions in the file and no imports, so no need to generate\n"
+ "// +extensionRegistry.\n");
+ }
}
- printer->Print("@end\n\n");
+ printer->Print("\n@end\n\n");
// File descriptor only needed if there are messages to use it.
if (message_generators_.size() > 0) {
- string syntax;
+ map<string, string> vars;
+ vars["root_class_name"] = root_class_name_;
+ vars["package"] = file_->package();
+ vars["objc_prefix"] = FileClassPrefix(file_);
switch (file_->syntax()) {
case FileDescriptor::SYNTAX_UNKNOWN:
- syntax = "GPBFileSyntaxUnknown";
+ vars["syntax"] = "GPBFileSyntaxUnknown";
break;
case FileDescriptor::SYNTAX_PROTO2:
- syntax = "GPBFileSyntaxProto2";
+ vars["syntax"] = "GPBFileSyntaxProto2";
break;
case FileDescriptor::SYNTAX_PROTO3:
- syntax = "GPBFileSyntaxProto3";
+ vars["syntax"] = "GPBFileSyntaxProto3";
break;
}
- printer->Print(
+ printer->Print(vars,
"#pragma mark - $root_class_name$_FileDescriptor\n"
"\n"
"static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n"
@@ -554,16 +487,24 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
" // about thread safety of the singleton.\n"
" static GPBFileDescriptor *descriptor = NULL;\n"
" if (!descriptor) {\n"
- " GPBDebugCheckRuntimeVersion();\n"
- " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
- " syntax:$syntax$];\n"
+ " GPBDebugCheckRuntimeVersion();\n");
+ if (vars["objc_prefix"].size() > 0) {
+ printer->Print(
+ vars,
+ " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
+ " objcPrefix:@\"$objc_prefix$\"\n"
+ " syntax:$syntax$];\n");
+ } else {
+ printer->Print(
+ vars,
+ " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
+ " syntax:$syntax$];\n");
+ }
+ printer->Print(
" }\n"
" return descriptor;\n"
"}\n"
- "\n",
- "root_class_name", root_class_name_,
- "package", file_->package(),
- "syntax", syntax);
+ "\n");
}
for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin();
@@ -582,24 +523,6 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
"// @@protoc_insertion_point(global_scope)\n");
}
-const vector<FileGenerator *> &FileGenerator::DependencyGenerators() {
- if (file_->dependency_count() != dependency_generators_.size()) {
- set<string> public_import_names;
- for (int i = 0; i < file_->public_dependency_count(); i++) {
- public_import_names.insert(file_->public_dependency(i)->name());
- }
- for (int i = 0; i < file_->dependency_count(); i++) {
- FileGenerator *generator =
- new FileGenerator(file_->dependency(i), options_);
- const string& name = file_->dependency(i)->name();
- bool public_import = (public_import_names.count(name) != 0);
- generator->SetIsPublicDependency(public_import);
- dependency_generators_.push_back(generator);
- }
- }
- return dependency_generators_;
-}
-
// Helper to print the import of the runtime support at the top of generated
// files. This currently only supports the runtime coming from a framework
// as defined by the official CocoaPod.
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h
index 8e4388d8..a60a6885 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h
@@ -62,32 +62,17 @@ class FileGenerator {
void GenerateHeader(io::Printer* printer);
const string& RootClassName() const { return root_class_name_; }
- const string Path() const { return FilePath(file_); }
- const FileDescriptor* Descriptor() const { return file_; }
-
- bool IsPublicDependency() const { return is_public_dep_; }
-
- protected:
- void SetIsPublicDependency(bool is_public_dep) {
- is_public_dep_ = is_public_dep;
- }
private:
const FileDescriptor* file_;
string root_class_name_;
- // Access this field through the DependencyGenerators accessor call below.
- // Do not reference it directly.
- vector<FileGenerator*> dependency_generators_;
-
vector<EnumGenerator*> enum_generators_;
vector<MessageGenerator*> message_generators_;
vector<ExtensionGenerator*> extension_generators_;
- bool is_public_dep_;
const Options options_;
- const vector<FileGenerator*>& DependencyGenerators();
void PrintFileRuntimePreamble(
io::Printer* printer, const string& header_to_import) const;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
index 29a8765c..36407467 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
@@ -45,12 +45,29 @@ ObjectiveCGenerator::ObjectiveCGenerator() {}
ObjectiveCGenerator::~ObjectiveCGenerator() {}
+bool ObjectiveCGenerator::HasGenerateAll() const {
+ return true;
+}
+
bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
const string& parameter,
- OutputDirectory* output_directory,
+ GeneratorContext* context,
string* error) const {
+ *error = "Unimplemented Generate() method. Call GenerateAll() instead.";
+ return false;
+}
+
+bool ObjectiveCGenerator::GenerateAll(const vector<const FileDescriptor*>& files,
+ const string& parameter,
+ GeneratorContext* context,
+ string* error) const {
// -----------------------------------------------------------------
- // Parse generator options.
+ // Parse generator options. These options are passed to the compiler using the
+ // --objc_opt flag. The options are passed as a comma separated list of
+ // options along with their values. If the option appears multiple times, only
+ // the last value will be considered.
+ //
+ // e.g. protoc ... --objc_opt=expected_prefixes=file.txt,generate_for_named_framework=MyFramework
Options generation_options;
@@ -70,7 +87,7 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
// (i.e. - "package=prefix # comment")
//
// There is no validation that the prefixes are good prefixes, it is
- // assume they are when you create the file.
+ // assumed that they are when you create the file.
generation_options.expected_prefixes_path = options[i].second;
} else if (options[i].first == "generate_for_named_framework") {
// The name of the framework that protos are being generated for. This
@@ -79,11 +96,12 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
//
// NOTE: If this option is used with
// named_framework_to_proto_path_mappings_path, then this is effectively
- // the "default" to use for everything that wasn't mapped by the other.
- generation_options.named_framework_to_proto_path_mappings_path = options[i].second;
+ // the "default" framework name used for everything that wasn't mapped by
+ // the mapping file.
+ generation_options.generate_for_named_framework = options[i].second;
} else if (options[i].first == "named_framework_to_proto_path_mappings_path") {
- // Path to find a file containing the listing of framework names and
- // proto files. The generator uses this to decide if another proto file
+ // Path to find a file containing the list of framework names and proto
+ // files. The generator uses this to decide if a proto file
// referenced should use a framework style import vs. a user level import
// (#import <FRAMEWORK/file.pbobjc.h> vs #import "dir/file.pbobjc.h").
//
@@ -97,8 +115,11 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
// with commas.
//
// There can be multiple lines listing the same frameworkName incase it
- // has a lot of proto files included in it; and having multiple lines
- // makes things easier to read.
+ // has a lot of proto files included in it; having multiple lines makes
+ // things easier to read. If a proto file is not configured in the
+ // mappings file, it will use the default framework name if one was passed
+ // with generate_for_named_framework, or the relative path to it's include
+ // path otherwise.
generation_options.named_framework_to_proto_path_mappings_path = options[i].second;
} else {
*error = "error: Unknown generator option: " + options[i].first;
@@ -108,29 +129,32 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
// -----------------------------------------------------------------
- // Validate the objc prefix/package pairing.
- if (!ValidateObjCClassPrefix(file, generation_options, error)) {
+ // Validate the objc prefix/package pairings.
+ if (!ValidateObjCClassPrefixes(files, generation_options, error)) {
// *error will have been filled in.
return false;
}
- FileGenerator file_generator(file, generation_options);
- string filepath = FilePath(file);
+ for (int i = 0; i < files.size(); i++) {
+ const FileDescriptor* file = files[i];
+ FileGenerator file_generator(file, generation_options);
+ string filepath = FilePath(file);
- // Generate header.
- {
- scoped_ptr<io::ZeroCopyOutputStream> output(
- output_directory->Open(filepath + ".pbobjc.h"));
- io::Printer printer(output.get(), '$');
- file_generator.GenerateHeader(&printer);
- }
+ // Generate header.
+ {
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ context->Open(filepath + ".pbobjc.h"));
+ io::Printer printer(output.get(), '$');
+ file_generator.GenerateHeader(&printer);
+ }
- // Generate m file.
- {
- scoped_ptr<io::ZeroCopyOutputStream> output(
- output_directory->Open(filepath + ".pbobjc.m"));
- io::Printer printer(output.get(), '$');
- file_generator.GenerateSource(&printer);
+ // Generate m file.
+ {
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ context->Open(filepath + ".pbobjc.m"));
+ io::Printer printer(output.get(), '$');
+ file_generator.GenerateSource(&printer);
+ }
}
return true;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/google/protobuf/compiler/objectivec/objectivec_generator.h
index 09266b04..9d801d51 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_generator.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.h
@@ -47,8 +47,15 @@ class LIBPROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator {
~ObjectiveCGenerator();
// implements CodeGenerator ----------------------------------------
- bool Generate(const FileDescriptor* file, const string& parameter,
- OutputDirectory* output_directory, string* error) const;
+ bool HasGenerateAll() const;
+ bool Generate(const FileDescriptor* file,
+ const string& parameter,
+ GeneratorContext* context,
+ string* error) const;
+ bool GenerateAll(const vector<const FileDescriptor*>& files,
+ const string& parameter,
+ GeneratorContext* context,
+ string* error) const;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectiveCGenerator);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
index 311bf35d..c7fd96ac 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
@@ -44,9 +44,10 @@
#include <google/protobuf/stubs/hash.h>
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
@@ -209,10 +210,14 @@ const char* const kReservedWordList[] = {
hash_set<string> kReservedWords =
MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList));
-string SanitizeNameForObjC(const string& input, const string& extension) {
+string SanitizeNameForObjC(const string& input,
+ const string& extension,
+ string* out_suffix_added) {
if (kReservedWords.count(input) > 0) {
+ if (out_suffix_added) *out_suffix_added = extension;
return input + extension;
}
+ if (out_suffix_added) out_suffix_added->clear();
return input;
}
@@ -261,6 +266,34 @@ bool IsSpecialName(const string& name, const string* special_names,
return false;
}
+string GetZeroEnumNameForFlagType(const FlagType flag_type) {
+ switch(flag_type) {
+ case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
+ return "GPBDescriptorInitializationFlag_None";
+ case FLAGTYPE_EXTENSION:
+ return "GPBExtensionNone";
+ case FLAGTYPE_FIELD:
+ return "GPBFieldNone";
+ default:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return "0";
+ }
+}
+
+string GetEnumNameForFlagType(const FlagType flag_type) {
+ switch(flag_type) {
+ case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
+ return "GPBDescriptorInitializationFlags";
+ case FLAGTYPE_EXTENSION:
+ return "GPBExtensionOptions";
+ case FLAGTYPE_FIELD:
+ return "GPBFieldFlags";
+ default:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return string();
+ }
+}
+
} // namespace
// Escape C++ trigraphs by escaping question marks to \?
@@ -307,6 +340,12 @@ string BaseFileName(const FileDescriptor* file) {
return basename;
}
+string FileClassPrefix(const FileDescriptor* file) {
+ // Default is empty string, no need to check has_objc_class_prefix.
+ string result = file->options().objc_class_prefix();
+ return result;
+}
+
string FilePath(const FileDescriptor* file) {
string output;
string basename;
@@ -337,19 +376,13 @@ string FilePathBasename(const FileDescriptor* file) {
return output;
}
-string FileClassPrefix(const FileDescriptor* file) {
- // Default is empty string, no need to check has_objc_class_prefix.
- string result = file->options().objc_class_prefix();
- return result;
-}
-
string FileClassName(const FileDescriptor* file) {
string name = FileClassPrefix(file);
name += UnderscoresToCamelCase(StripProto(BaseFileName(file)), true);
name += "Root";
// There aren't really any reserved words that end in "Root", but playing
// it safe and checking.
- return SanitizeNameForObjC(name, "_RootClass");
+ return SanitizeNameForObjC(name, "_RootClass", NULL);
}
string ClassNameWorker(const Descriptor* descriptor) {
@@ -371,11 +404,15 @@ string ClassNameWorker(const EnumDescriptor* descriptor) {
}
string ClassName(const Descriptor* descriptor) {
+ return ClassName(descriptor, NULL);
+}
+
+string ClassName(const Descriptor* descriptor, string* out_suffix_added) {
// 1. Message names are used as is (style calls for CamelCase, trust it).
// 2. Check for reserved word at the very end and then suffix things.
string prefix = FileClassPrefix(descriptor->file());
string name = ClassNameWorker(descriptor);
- return SanitizeNameForObjC(prefix + name, "_Class");
+ return SanitizeNameForObjC(prefix + name, "_Class", out_suffix_added);
}
string EnumName(const EnumDescriptor* descriptor) {
@@ -389,7 +426,7 @@ string EnumName(const EnumDescriptor* descriptor) {
// yields Fixed_Class, Fixed_Size.
string name = FileClassPrefix(descriptor->file());
name += ClassNameWorker(descriptor);
- return SanitizeNameForObjC(name, "_Enum");
+ return SanitizeNameForObjC(name, "_Enum", NULL);
}
string EnumValueName(const EnumValueDescriptor* descriptor) {
@@ -404,7 +441,7 @@ string EnumValueName(const EnumValueDescriptor* descriptor) {
const string& name = class_name + "_" + value_str;
// There aren't really any reserved words with an underscore and a leading
// capital letter, but playing it safe and checking.
- return SanitizeNameForObjC(name, "_Value");
+ return SanitizeNameForObjC(name, "_Value", NULL);
}
string EnumValueShortName(const EnumValueDescriptor* descriptor) {
@@ -441,7 +478,7 @@ string UnCamelCaseEnumShortName(const string& name) {
string ExtensionMethodName(const FieldDescriptor* descriptor) {
const string& name = NameFromFieldDescriptor(descriptor);
const string& result = UnderscoresToCamelCase(name, false);
- return SanitizeNameForObjC(result, "_Extension");
+ return SanitizeNameForObjC(result, "_Extension", NULL);
}
string FieldName(const FieldDescriptor* field) {
@@ -456,7 +493,7 @@ string FieldName(const FieldDescriptor* field) {
result += "_p";
}
}
- return SanitizeNameForObjC(result, "_p");
+ return SanitizeNameForObjC(result, "_p", NULL);
}
string FieldNameCapitalized(const FieldDescriptor* field) {
@@ -816,21 +853,26 @@ bool HasNonZeroDefaultValue(const FieldDescriptor* field) {
return false;
}
-string BuildFlagsString(const vector<string>& strings) {
+string BuildFlagsString(const FlagType flag_type,
+ const vector<string>& strings) {
if (strings.size() == 0) {
- return "0";
+ return GetZeroEnumNameForFlagType(flag_type);
+ } else if (strings.size() == 1) {
+ return strings[0];
}
- string string;
+ string string("(" + GetEnumNameForFlagType(flag_type) + ")(");
for (size_t i = 0; i != strings.size(); ++i) {
if (i > 0) {
string.append(" | ");
}
string.append(strings[i]);
}
+ string.append(")");
return string;
}
-string BuildCommentsString(const SourceLocation& location) {
+string BuildCommentsString(const SourceLocation& location,
+ bool prefer_single_line) {
const string& comments = location.leading_comments.empty()
? location.trailing_comments
: location.leading_comments;
@@ -839,15 +881,45 @@ string BuildCommentsString(const SourceLocation& location) {
while (!lines.empty() && lines.back().empty()) {
lines.pop_back();
}
- string prefix("///");
- string suffix("\n");
+ // If there are no comments, just return an empty string.
+ if (lines.size() == 0) {
+ return "";
+ }
+
+ string prefix;
+ string suffix;
string final_comments;
- for (int i = 0; i < lines.size(); i++) {
- // HeaderDoc uses '\' and '@' for markers; escape them.
- const string line = StringReplace(lines[i], "\\", "\\\\", true);
- final_comments +=
- prefix + StringReplace(line, "@", "\\@", true) + suffix;
+ string epilogue;
+
+ bool add_leading_space = false;
+
+ if (prefer_single_line && lines.size() == 1) {
+ prefix = "/** ";
+ suffix = " */\n";
+ } else {
+ prefix = "* ";
+ suffix = "\n";
+ final_comments += "/**\n";
+ epilogue = " **/\n";
+ add_leading_space = true;
}
+
+ for (int i = 0; i < lines.size(); i++) {
+ string line = StripPrefixString(lines[i], " ");
+ // HeaderDoc and appledoc use '\' and '@' for markers; escape them.
+ line = StringReplace(line, "\\", "\\\\", true);
+ line = StringReplace(line, "@", "\\@", true);
+ // Decouple / from * to not have inline comments inside comments.
+ line = StringReplace(line, "/*", "/\\*", true);
+ line = StringReplace(line, "*/", "*\\/", true);
+ line = prefix + line;
+ StripWhitespace(&line);
+ // If not a one line, need to add the first space before *, as
+ // StripWhitespace would have removed it.
+ line = (add_leading_space ? " " : "") + line;
+ final_comments += line + suffix;
+ }
+ final_comments += epilogue;
return final_comments;
}
@@ -948,28 +1020,20 @@ bool LoadExpectedPackagePrefixes(const Options &generation_options,
generation_options.expected_prefixes_path, &collector, out_error);
}
-} // namespace
-
-bool ValidateObjCClassPrefix(const FileDescriptor* file,
- const Options& generation_options,
- string* out_error) {
+bool ValidateObjCClassPrefix(
+ const FileDescriptor* file,
+ const string& expected_prefixes_path,
+ const map<string, string>& expected_package_prefixes,
+ string* out_error) {
const string prefix = file->options().objc_class_prefix();
const string package = file->package();
// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
// error cases, so it seems to be ok to use as a back door for warnings.
- // Load any expected package prefixes to validate against those.
- map<string, string> expected_package_prefixes;
- if (!LoadExpectedPackagePrefixes(generation_options,
- &expected_package_prefixes,
- out_error)) {
- return false;
- }
-
// Check: Error - See if there was an expected prefix for the package and
// report if it doesn't match (wrong or missing).
- map<string, string>::iterator package_match =
+ map<string, string>::const_iterator package_match =
expected_package_prefixes.find(package);
if (package_match != expected_package_prefixes.end()) {
// There was an entry, and...
@@ -990,27 +1054,11 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file,
}
// If there was no prefix option, we're done at this point.
- if (prefix.length() == 0) {
+ if (prefix.empty()) {
// No prefix, nothing left to check.
return true;
}
- // Check: Error - Make sure the prefix wasn't expected for a different
- // package (overlap is allowed, but it has to be listed as an expected
- // overlap).
- for (map<string, string>::iterator i = expected_package_prefixes.begin();
- i != expected_package_prefixes.end(); ++i) {
- if (i->second == prefix) {
- *out_error =
- "error: Found 'option objc_class_prefix = \"" + prefix +
- "\";' in '" + file->name() +
- "'; that prefix is already used for 'package " + i->first +
- ";'. It can only be reused by listing it in the expected file (" +
- generation_options.expected_prefixes_path + ").";
- return false; // Only report first usage of the prefix.
- }
- }
-
// Check: Warning - Make sure the prefix is is a reasonable value according
// to Apple's rules (the checks above implicitly whitelist anything that
// doesn't meet these rules).
@@ -1032,6 +1080,56 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file,
cerr.flush();
}
+ // Look for any other package that uses the same prefix.
+ string other_package_for_prefix;
+ for (map<string, string>::const_iterator i = expected_package_prefixes.begin();
+ i != expected_package_prefixes.end(); ++i) {
+ if (i->second == prefix) {
+ other_package_for_prefix = i->first;
+ break;
+ }
+ }
+
+ // Check: Warning - If the file does not have a package, check whether
+ // the prefix declared is being used by another package or not.
+ if (package.empty()) {
+ // The file does not have a package and ...
+ if (other_package_for_prefix.empty()) {
+ // ... no other package has declared that prefix.
+ cerr << endl
+ << "protoc:0: warning: File '" << file->name() << "' has no "
+ << "package. Consider adding a new package to the proto and adding '"
+ << "new.package = " << prefix << "' to the expected prefixes file ("
+ << expected_prefixes_path << ")." << endl;
+ cerr.flush();
+ } else {
+ // ... another package has declared the same prefix.
+ cerr << endl
+ << "protoc:0: warning: File '" << file->name() << "' has no package "
+ << "and package '" << other_package_for_prefix << "' already uses '"
+ << prefix << "' as its prefix. Consider either adding a new package "
+ << "to the proto, or reusing one of the packages already using this "
+ << "prefix in the expected prefixes file ("
+ << expected_prefixes_path << ")." << endl;
+ cerr.flush();
+ }
+ return true;
+ }
+
+ // Check: Error - Make sure the prefix wasn't expected for a different
+ // package (overlap is allowed, but it has to be listed as an expected
+ // overlap).
+ if (!other_package_for_prefix.empty()) {
+ *out_error =
+ "error: Found 'option objc_class_prefix = \"" + prefix +
+ "\";' in '" + file->name() +
+ "'; that prefix is already used for 'package " +
+ other_package_for_prefix + ";'. It can only be reused by listing " +
+ "it in the expected file (" +
+ expected_prefixes_path + ").";
+ return false; // Only report first usage of the prefix.
+ }
+
// Check: Warning - If the given package/prefix pair wasn't expected, issue a
// warning issue a warning suggesting it gets added to the file.
if (!expected_package_prefixes.empty()) {
@@ -1039,13 +1137,39 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file,
<< "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
<< prefix << "\";' in '" << file->name() << "';"
<< " consider adding it to the expected prefixes file ("
- << generation_options.expected_prefixes_path << ")." << endl;
+ << expected_prefixes_path << ")." << endl;
cerr.flush();
}
return true;
}
+} // namespace
+
+bool ValidateObjCClassPrefixes(const vector<const FileDescriptor*>& files,
+ const Options& generation_options,
+ string* out_error) {
+ // Load the expected package prefixes, if available, to validate against.
+ map<string, string> expected_package_prefixes;
+ if (!LoadExpectedPackagePrefixes(generation_options,
+ &expected_package_prefixes,
+ out_error)) {
+ return false;
+ }
+
+ for (int i = 0; i < files.size(); i++) {
+ bool is_valid =
+ ValidateObjCClassPrefix(files[i],
+ generation_options.expected_prefixes_path,
+ expected_package_prefixes,
+ out_error);
+ if (!is_valid) {
+ return false;
+ }
+ }
+ return true;
+}
+
TextFormatDecodeData::TextFormatDecodeData() { }
TextFormatDecodeData::~TextFormatDecodeData() { }
@@ -1306,7 +1430,8 @@ bool Parser::Finish() {
return true;
}
// Force a newline onto the end to finish parsing.
- p_ = StringPiece(leftover_ + "\n");
+ leftover_ += "\n";
+ p_ = StringPiece(leftover_);
if (!ParseLoop()) {
return false;
}
@@ -1367,6 +1492,178 @@ bool ParseSimpleFile(
return parser.Finish();
}
+ImportWriter::ImportWriter(
+ const string& generate_for_named_framework,
+ const string& named_framework_to_proto_path_mappings_path)
+ : generate_for_named_framework_(generate_for_named_framework),
+ named_framework_to_proto_path_mappings_path_(
+ named_framework_to_proto_path_mappings_path),
+ need_to_parse_mapping_file_(true) {
+}
+
+ImportWriter::~ImportWriter() {}
+
+void ImportWriter::AddFile(const FileDescriptor* file,
+ const string& header_extension) {
+ const string file_path(FilePath(file));
+
+ if (IsProtobufLibraryBundledProtoFile(file)) {
+ protobuf_framework_imports_.push_back(
+ FilePathBasename(file) + header_extension);
+ protobuf_non_framework_imports_.push_back(file_path + header_extension);
+ return;
+ }
+
+ // Lazy parse any mappings.
+ if (need_to_parse_mapping_file_) {
+ ParseFrameworkMappings();
+ }
+
+ map<string, string>::iterator proto_lookup =
+ proto_file_to_framework_name_.find(file->name());
+ if (proto_lookup != proto_file_to_framework_name_.end()) {
+ other_framework_imports_.push_back(
+ proto_lookup->second + "/" +
+ FilePathBasename(file) + header_extension);
+ return;
+ }
+
+ if (!generate_for_named_framework_.empty()) {
+ other_framework_imports_.push_back(
+ generate_for_named_framework_ + "/" +
+ FilePathBasename(file) + header_extension);
+ return;
+ }
+
+ other_imports_.push_back(file_path + header_extension);
+}
+
+void ImportWriter::Print(io::Printer* printer) const {
+ assert(protobuf_non_framework_imports_.size() ==
+ protobuf_framework_imports_.size());
+
+ bool add_blank_line = false;
+
+ if (protobuf_framework_imports_.size() > 0) {
+ const string framework_name(ProtobufLibraryFrameworkName);
+ const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name));
+
+ printer->Print(
+ "#if $cpp_symbol$\n",
+ "cpp_symbol", cpp_symbol);
+ for (vector<string>::const_iterator iter = protobuf_framework_imports_.begin();
+ iter != protobuf_framework_imports_.end(); ++iter) {
+ printer->Print(
+ " #import <$framework_name$/$header$>\n",
+ "framework_name", framework_name,
+ "header", *iter);
+ }
+ printer->Print(
+ "#else\n");
+ for (vector<string>::const_iterator iter = protobuf_non_framework_imports_.begin();
+ iter != protobuf_non_framework_imports_.end(); ++iter) {
+ printer->Print(
+ " #import \"$header$\"\n",
+ "header", *iter);
+ }
+ printer->Print(
+ "#endif\n");
+
+ add_blank_line = true;
+ }
+
+ if (other_framework_imports_.size() > 0) {
+ if (add_blank_line) {
+ printer->Print("\n");
+ }
+
+ for (vector<string>::const_iterator iter = other_framework_imports_.begin();
+ iter != other_framework_imports_.end(); ++iter) {
+ printer->Print(
+ " #import <$header$>\n",
+ "header", *iter);
+ }
+
+ add_blank_line = true;
+ }
+
+ if (other_imports_.size() > 0) {
+ if (add_blank_line) {
+ printer->Print("\n");
+ }
+
+ for (vector<string>::const_iterator iter = other_imports_.begin();
+ iter != other_imports_.end(); ++iter) {
+ printer->Print(
+ " #import \"$header$\"\n",
+ "header", *iter);
+ }
+ }
+}
+
+void ImportWriter::ParseFrameworkMappings() {
+ need_to_parse_mapping_file_ = false;
+ if (named_framework_to_proto_path_mappings_path_.empty()) {
+ return; // Nothing to do.
+ }
+
+ ProtoFrameworkCollector collector(&proto_file_to_framework_name_);
+ string parse_error;
+ if (!ParseSimpleFile(named_framework_to_proto_path_mappings_path_,
+ &collector, &parse_error)) {
+ cerr << "error parsing " << named_framework_to_proto_path_mappings_path_
+ << " : " << parse_error << endl;
+ cerr.flush();
+ }
+}
+
+bool ImportWriter::ProtoFrameworkCollector::ConsumeLine(
+ const StringPiece& line, string* out_error) {
+ int offset = line.find(':');
+ if (offset == StringPiece::npos) {
+ *out_error =
+ string("Framework/proto file mapping line without colon sign: '") +
+ line.ToString() + "'.";
+ return false;
+ }
+ StringPiece framework_name(line, 0, offset);
+ StringPiece proto_file_list(line, offset + 1, line.length() - offset - 1);
+ StringPieceTrimWhitespace(&framework_name);
+
+ int start = 0;
+ while (start < proto_file_list.length()) {
+ offset = proto_file_list.find(',', start);
+ if (offset == StringPiece::npos) {
+ offset = proto_file_list.length();
+ }
+
+ StringPiece proto_file(proto_file_list, start, offset - start);
+ StringPieceTrimWhitespace(&proto_file);
+ if (proto_file.size() != 0) {
+ map<string, string>::iterator existing_entry =
+ map_->find(proto_file.ToString());
+ if (existing_entry != map_->end()) {
+ cerr << "warning: duplicate proto file reference, replacing framework entry for '"
+ << proto_file.ToString() << "' with '" << framework_name.ToString()
+ << "' (was '" << existing_entry->second << "')." << endl;
+ cerr.flush();
+ }
+
+ if (proto_file.find(' ') != StringPiece::npos) {
+ cerr << "note: framework mapping file had a proto file with a space in, hopefully that isn't a missing comma: '"
+ << proto_file.ToString() << "'" << endl;
+ cerr.flush();
+ }
+
+ (*map_)[proto_file.ToString()] = framework_name.ToString();
+ }
+
+ start = offset + 1;
+ }
+
+ return true;
+}
+
} // namespace objectivec
} // namespace compiler
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
index be20beee..d17d44aa 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
@@ -67,6 +67,9 @@ bool IsRetainedName(const string& name);
// handling under ARC.
bool IsInitName(const string& name);
+// Gets the objc_class_prefix.
+string FileClassPrefix(const FileDescriptor* file);
+
// Gets the path of the file we're going to generate (sans the .pb.h
// extension). The path will be dependent on the objectivec package
// declared in the proto package.
@@ -83,6 +86,7 @@ string FileClassName(const FileDescriptor* file);
// These return the fully-qualified class name corresponding to the given
// descriptor.
string ClassName(const Descriptor* descriptor);
+string ClassName(const Descriptor* descriptor, string* out_suffix_added);
string EnumName(const EnumDescriptor* descriptor);
// Returns the fully-qualified name of the enum value corresponding to the
@@ -137,6 +141,12 @@ enum ObjectiveCType {
OBJECTIVECTYPE_MESSAGE
};
+enum FlagType {
+ FLAGTYPE_DESCRIPTOR_INITIALIZATION,
+ FLAGTYPE_EXTENSION,
+ FLAGTYPE_FIELD
+};
+
template<class TDescriptor>
string GetOptionalDeprecatedAttribute(const TDescriptor* descriptor, bool preSpace = true, bool postNewline = false) {
if (descriptor->options().deprecated()) {
@@ -168,10 +178,12 @@ string GPBGenericValueFieldName(const FieldDescriptor* field);
string DefaultValue(const FieldDescriptor* field);
bool HasNonZeroDefaultValue(const FieldDescriptor* field);
-string BuildFlagsString(const vector<string>& strings);
+string BuildFlagsString(const FlagType type, const vector<string>& strings);
-// Builds a HeaderDoc style comment out of the comments in the .proto file.
-string BuildCommentsString(const SourceLocation& location);
+// Builds HeaderDoc/appledoc style comments out of the comments in the .proto
+// file.
+string BuildCommentsString(const SourceLocation& location,
+ bool prefer_single_line);
// The name the commonly used by the library when built as a framework.
// This lines up to the name used in the CocoaPod.
@@ -183,12 +195,12 @@ string ProtobufFrameworkImportSymbol(const string& framework_name);
// Checks if the file is one of the proto's bundled with the library.
bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file);
-// Checks the prefix for a given file and outputs any warnings needed, if
-// there are flat out errors, then out_error is filled in and the result is
-// false.
-bool ValidateObjCClassPrefix(const FileDescriptor* file,
- const Options& generation_options,
- string* out_error);
+// Checks the prefix for the given files and outputs any warnings as needed. If
+// there are flat out errors, then out_error is filled in with the first error
+// and the result is false.
+bool ValidateObjCClassPrefixes(const vector<const FileDescriptor*>& files,
+ const Options& generation_options,
+ string* out_error);
// Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform
// the input into the expected output.
@@ -223,6 +235,43 @@ class LIBPROTOC_EXPORT LineConsumer {
bool ParseSimpleFile(
const string& path, LineConsumer* line_consumer, string* out_error);
+
+// Helper class for parsing framework import mappings and generating
+// import statements.
+class LIBPROTOC_EXPORT ImportWriter {
+ public:
+ ImportWriter(const string& generate_for_named_framework,
+ const string& named_framework_to_proto_path_mappings_path);
+ ~ImportWriter();
+
+ void AddFile(const FileDescriptor* file, const string& header_extension);
+ void Print(io::Printer *printer) const;
+
+ private:
+ class ProtoFrameworkCollector : public LineConsumer {
+ public:
+ ProtoFrameworkCollector(map<string, string>* inout_proto_file_to_framework_name)
+ : map_(inout_proto_file_to_framework_name) {}
+
+ virtual bool ConsumeLine(const StringPiece& line, string* out_error);
+
+ private:
+ map<string, string>* map_;
+ };
+
+ void ParseFrameworkMappings();
+
+ const string generate_for_named_framework_;
+ const string named_framework_to_proto_path_mappings_path_;
+ map<string, string> proto_file_to_framework_name_;
+ bool need_to_parse_mapping_file_;
+
+ vector<string> protobuf_framework_imports_;
+ vector<string> protobuf_non_framework_imports_;
+ vector<string> other_framework_imports_;
+ vector<string> other_imports_;
+};
+
} // namespace objectivec
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
index ac5d8aea..0bc9dc10 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
@@ -115,7 +115,7 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
if (value_field_flags.find("GPBFieldHasEnumDescriptor") != string::npos) {
field_flags.push_back("GPBFieldHasEnumDescriptor");
}
- variables_["fieldflags"] = BuildFlagsString(field_flags);
+ variables_["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags);
ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
const bool value_is_object_type =
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
index e1a78619..4c6e1b55 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
@@ -331,7 +331,7 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
string message_comments;
SourceLocation location;
if (descriptor_->GetSourceLocation(&location)) {
- message_comments = BuildCommentsString(location);
+ message_comments = BuildCommentsString(location, false);
} else {
message_comments = "";
}
@@ -521,7 +521,8 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
if (descriptor_->options().message_set_wire_format()) {
init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat");
}
- vars["init_flags"] = BuildFlagsString(init_flags);
+ vars["init_flags"] = BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION,
+ init_flags);
printer->Print(
vars,
@@ -579,6 +580,19 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
" [localDescriptor setupExtensionRanges:ranges\n"
" count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
}
+ if (descriptor_->containing_type() != NULL) {
+ string parent_class_name = ClassName(descriptor_->containing_type());
+ printer->Print(
+ " [localDescriptor setupContainingMessageClassName:GPBStringifySymbol($parent_name$)];\n",
+ "parent_name", parent_class_name);
+ }
+ string suffix_added;
+ ClassName(descriptor_, &suffix_added);
+ if (suffix_added.size() > 0) {
+ printer->Print(
+ " [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n",
+ "suffix", suffix_added);
+ }
printer->Print(
" NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
" descriptor = localDescriptor;\n"
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
index 44bafd7f..5531ae24 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
@@ -53,7 +53,7 @@ OneofGenerator::OneofGenerator(const OneofDescriptor* descriptor)
string comments;
SourceLocation location;
if (descriptor_->GetSourceLocation(&location)) {
- comments = BuildCommentsString(location);
+ comments = BuildCommentsString(location, true);
} else {
comments = "";
}
@@ -104,7 +104,9 @@ void OneofGenerator::GeneratePublicCasePropertyDeclaration(
void OneofGenerator::GenerateClearFunctionDeclaration(io::Printer* printer) {
printer->Print(
variables_,
- "/// Clears whatever value was set for the oneof '$name$'.\n"
+ "/**\n"
+ " * Clears whatever value was set for the oneof '$name$'.\n"
+ " **/\n"
"void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message);\n");
}
@@ -119,7 +121,7 @@ void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) {
variables_,
"void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n"
" GPBDescriptor *descriptor = [message descriptor];\n"
- " GPBOneofDescriptor *oneof = descriptor->oneofs_[$raw_index$];\n"
+ " GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:$raw_index$];\n"
" GPBMaybeClearOneof(message, oneof, $index$, 0);\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index 214d7c9c..519ed8fc 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -525,7 +525,6 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
SourceCodeInfo source_code_info;
source_code_info_ = &source_code_info;
- vector<string> top_doc_comments;
if (LookingAtType(io::Tokenizer::TYPE_START)) {
// Advance to first token.
input_->NextWithComments(NULL, &upcoming_detached_comments_,
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index c4d48fc6..9064c382 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -36,6 +36,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
} // namespace
+void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
const ::google::protobuf::FileDescriptor* file =
@@ -102,6 +103,7 @@ inline void protobuf_AssignDescriptorsOnce() {
&protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
}
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
@@ -123,6 +125,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
delete CodeGeneratorResponse_File_reflection_;
}
+void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
static bool already_here = false;
if (already_here) return;
@@ -161,16 +164,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto
}
} static_descriptor_initializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto_;
-namespace {
-
-static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
-static void MergeFromFail(int line) {
- GOOGLE_CHECK(false) << __FILE__ << ":" << line;
-}
-
-} // namespace
-
-
// ===================================================================
#if !defined(_MSC_VER) || _MSC_VER >= 1900
@@ -451,7 +444,9 @@ int CodeGeneratorRequest::ByteSize() const {
void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const CodeGeneratorRequest* source =
::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorRequest>(
&from);
@@ -466,7 +461,9 @@ void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) {
void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
file_to_generate_.MergeFrom(from.file_to_generate_);
proto_file_.MergeFrom(from.proto_file_);
if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
@@ -962,7 +959,9 @@ int CodeGeneratorResponse_File::ByteSize() const {
void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const CodeGeneratorResponse_File* source =
::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse_File>(
&from);
@@ -977,7 +976,9 @@ void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& fr
void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name()) {
set_has_name();
@@ -1269,7 +1270,9 @@ int CodeGeneratorResponse::ByteSize() const {
void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const CodeGeneratorResponse* source =
::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse>(
&from);
@@ -1284,7 +1287,9 @@ void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) {
void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
file_.MergeFrom(from.file_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_error()) {
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index cc54a8ab..d5468a0c 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -44,6 +44,7 @@
// performance-minded Python code leverage the fast C++ implementation
// directly.
+#include <algorithm>
#include <google/protobuf/stubs/hash.h>
#include <limits>
#include <map>
@@ -107,20 +108,25 @@ string ModuleAlias(const string& filename) {
return module_name;
}
-
-// Returns an import statement of form "from X.Y.Z import T" for the given
-// .proto filename.
-string ModuleImportStatement(const string& filename) {
- string module_name = ModuleName(filename);
- int last_dot_pos = module_name.rfind('.');
- if (last_dot_pos == string::npos) {
- // NOTE(petya): this is not tested as it would require a protocol buffer
- // outside of any package, and I don't think that is easily achievable.
- return "import " + module_name;
- } else {
- return "from " + module_name.substr(0, last_dot_pos) + " import " +
- module_name.substr(last_dot_pos + 1);
+// Keywords reserved by the Python language.
+const char* const kKeywords[] = {
+ "False", "None", "True", "and", "as", "assert", "break",
+ "class", "continue", "def", "del", "elif", "else", "except",
+ "finally", "for", "from", "global", "if", "import", "in",
+ "is", "lambda", "nonlocal", "not", "or", "pass", "raise",
+ "return", "try", "while", "with", "yield",
+};
+const char* const* kKeywordsEnd =
+ kKeywords + (sizeof(kKeywords) / sizeof(kKeywords[0]));
+
+bool ContainsPythonKeyword(const string& module_name) {
+ vector<string> tokens = Split(module_name, ".");
+ for (int i = 0; i < tokens.size(); ++i) {
+ if (std::find(kKeywords, kKeywordsEnd, tokens[i]) != kKeywordsEnd) {
+ return true;
+ }
}
+ return false;
}
@@ -359,10 +365,32 @@ bool Generator::Generate(const FileDescriptor* file,
void Generator::PrintImports() const {
for (int i = 0; i < file_->dependency_count(); ++i) {
const string& filename = file_->dependency(i)->name();
- string import_statement = ModuleImportStatement(filename);
+
+ string module_name = ModuleName(filename);
string module_alias = ModuleAlias(filename);
- printer_->Print("$statement$ as $alias$\n", "statement",
- import_statement, "alias", module_alias);
+ if (ContainsPythonKeyword(module_name)) {
+ // If the module path contains a Python keyword, we have to quote the
+ // module name and import it using importlib. Otherwise the usual kind of
+ // import statement would result in a syntax error from the presence of
+ // the keyword.
+ printer_->Print("import importlib\n");
+ printer_->Print("$alias$ = importlib.import_module('$name$')\n", "alias",
+ module_alias, "name", module_name);
+ } else {
+ int last_dot_pos = module_name.rfind('.');
+ string import_statement;
+ if (last_dot_pos == string::npos) {
+ // NOTE(petya): this is not tested as it would require a protocol buffer
+ // outside of any package, and I don't think that is easily achievable.
+ import_statement = "import " + module_name;
+ } else {
+ import_statement = "from " + module_name.substr(0, last_dot_pos) +
+ " import " + module_name.substr(last_dot_pos + 1);
+ }
+ printer_->Print("$statement$ as $alias$\n", "statement", import_statement,
+ "alias", module_alias);
+ }
+
CopyPublicDependenciesAliases(module_alias, file_->dependency(i));
}
printer_->Print("\n");
diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
index 23f2449c..34f857fd 100644
--- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
@@ -46,6 +46,7 @@
#include <google/protobuf/testing/file.h>
#include <google/protobuf/testing/file.h>
+#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
@@ -115,6 +116,53 @@ TEST(PythonPluginTest, PluginTest) {
EXPECT_EQ(0, cli.Run(5, argv));
}
+// This test verifies that the generated Python output uses regular imports (as
+// opposed to importlib) in the usual case where the .proto file paths do not
+// not contain any Python keywords.
+TEST(PythonPluginTest, ImportTest) {
+ // Create files test1.proto and test2.proto with the former importing the
+ // latter.
+ GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test1.proto",
+ "syntax = \"proto3\";\n"
+ "package foo;\n"
+ "import \"test2.proto\";"
+ "message Message1 {\n"
+ " Message2 message_2 = 1;\n"
+ "}\n",
+ true));
+ GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test2.proto",
+ "syntax = \"proto3\";\n"
+ "package foo;\n"
+ "message Message2 {}\n",
+ true));
+
+ google::protobuf::compiler::CommandLineInterface cli;
+ cli.SetInputsAreProtoPathRelative(true);
+ python::Generator python_generator;
+ cli.RegisterGenerator("--python_out", &python_generator, "");
+ string proto_path = "-I" + TestTempDir();
+ string python_out = "--python_out=" + TestTempDir();
+ const char* argv[] = {"protoc", proto_path.c_str(), "-I.", python_out.c_str(),
+ "test1.proto"};
+ ASSERT_EQ(0, cli.Run(5, argv));
+
+ // Loop over the lines of the generated code and verify that we find an
+ // ordinary Python import but do not find the string "importlib".
+ string output;
+ GOOGLE_CHECK_OK(File::GetContents(TestTempDir() + "/test1_pb2.py", &output,
+ true));
+ std::vector<string> lines = Split(output, "\n");
+ string expected_import = "import test2_pb2";
+ bool found_expected_import = false;
+ for (int i = 0; i < lines.size(); ++i) {
+ if (lines[i].find(expected_import) != string::npos) {
+ found_expected_import = true;
+ }
+ EXPECT_EQ(string::npos, lines[i].find("importlib"));
+ }
+ EXPECT_TRUE(found_expected_import);
+}
+
} // namespace
} // namespace python
} // namespace compiler
diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_code.rb b/src/google/protobuf/compiler/ruby/ruby_generated_code_pb.rb
index 49b23fbe..49b23fbe 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generated_code.rb
+++ b/src/google/protobuf/compiler/ruby/ruby_generated_code_pb.rb
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc
index 92c76fb0..fbe3b4cb 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator.cc
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc
@@ -48,7 +48,7 @@ namespace ruby {
// Forward decls.
std::string IntToString(int32 value);
-std::string StripDotProto(const std::string& proto_file);
+std::string GetRequireName(const std::string& proto_file);
std::string LabelForField(google::protobuf::FieldDescriptor* field);
std::string TypeName(google::protobuf::FieldDescriptor* field);
void GenerateMessage(const google::protobuf::Descriptor* message,
@@ -70,13 +70,13 @@ std::string IntToString(int32 value) {
return os.str();
}
-std::string StripDotProto(const std::string& proto_file) {
+std::string GetRequireName(const std::string& proto_file) {
int lastindex = proto_file.find_last_of(".");
- return proto_file.substr(0, lastindex);
+ return proto_file.substr(0, lastindex) + "_pb";
}
std::string GetOutputFilename(const std::string& proto_file) {
- return StripDotProto(proto_file) + ".rb";
+ return GetRequireName(proto_file) + ".rb";
}
std::string LabelForField(const google::protobuf::FieldDescriptor* field) {
@@ -237,15 +237,52 @@ void GenerateEnum(const google::protobuf::EnumDescriptor* en,
"end\n");
}
-// Module names, class names, and enum value names need to be Ruby constants,
-// which must start with a capital letter.
+// Locale-agnostic utility functions.
+bool IsLower(char ch) { return ch >= 'a' && ch <= 'z'; }
+
+bool IsUpper(char ch) { return ch >= 'A' && ch <= 'Z'; }
+
+bool IsAlpha(char ch) { return IsLower(ch) || IsUpper(ch); }
+
+char ToUpper(char ch) { return IsLower(ch) ? (ch - 'a' + 'A') : ch; }
+
+
+// Package names in protobuf are snake_case by convention, but Ruby module
+// names must be PascalCased.
+//
+// foo_bar_baz -> FooBarBaz
+std::string PackageToModule(const std::string& name) {
+ bool next_upper = true;
+ std::string result;
+ result.reserve(name.size());
+
+ for (int i = 0; i < name.size(); i++) {
+ if (name[i] == '_') {
+ next_upper = true;
+ } else {
+ if (next_upper) {
+ result.push_back(ToUpper(name[i]));
+ } else {
+ result.push_back(name[i]);
+ }
+ next_upper = false;
+ }
+ }
+
+ return result;
+}
+
+// Class and enum names in protobuf should be PascalCased by convention, but
+// since there is nothing enforcing this we need to ensure that they are valid
+// Ruby constants. That mainly means making sure that the first character is
+// an upper-case letter.
std::string RubifyConstant(const std::string& name) {
std::string ret = name;
if (!ret.empty()) {
- if (ret[0] >= 'a' && ret[0] <= 'z') {
+ if (IsLower(ret[0])) {
// If it starts with a lowercase letter, capitalize it.
- ret[0] = ret[0] - 'a' + 'A';
- } else if (ret[0] < 'A' || ret[0] > 'Z') {
+ ret[0] = ToUpper(ret[0]);
+ } else if (!IsAlpha(ret[0])) {
// Otherwise (e.g. if it begins with an underscore), we need to come up
// with some prefix that starts with a capital letter. We could be smarter
// here, e.g. try to strip leading underscores, but this may cause other
@@ -254,6 +291,7 @@ std::string RubifyConstant(const std::string& name) {
ret = "PB_" + ret;
}
}
+
return ret;
}
@@ -314,7 +352,7 @@ int GeneratePackageModules(
component = package_name.substr(0, dot_index);
package_name = package_name.substr(dot_index + 1);
}
- component = RubifyConstant(component);
+ component = PackageToModule(component);
printer->Print(
"module $name$\n",
"name", component);
@@ -391,7 +429,7 @@ bool MaybeEmitDependency(const FileDescriptor* import,
return true;
} else {
printer->Print(
- "require '$name$'\n", "name", StripDotProto(import->name()));
+ "require '$name$'\n", "name", GetRequireName(import->name()));
return true;
}
}
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
index c0acb407..1aabe8aa 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
+++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
@@ -91,12 +91,12 @@ TEST(RubyGeneratorTest, GeneratorTest) {
// Load the generated output and compare to the expected result.
string output;
GOOGLE_CHECK_OK(File::GetContents(
- TestTempDir() + "/ruby_generated_code.rb",
+ TestTempDir() + "/ruby_generated_code_pb.rb",
&output,
true));
string expected_output;
GOOGLE_CHECK_OK(File::GetContents(
- ruby_tests + "/ruby_generated_code.rb",
+ ruby_tests + "/ruby_generated_code_pb.rb",
&expected_output,
true));
EXPECT_EQ(expected_output, output);
diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc
index 6e258664..e929e4fb 100644
--- a/src/google/protobuf/compiler/subprocess.cc
+++ b/src/google/protobuf/compiler/subprocess.cc
@@ -261,12 +261,12 @@ string Subprocess::Win32ErrorMessage(DWORD error_code) {
char* message;
// WTF?
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, error_code, 0,
- (LPTSTR)&message, // NOT A BUG!
- 0, NULL);
+ FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, error_code, 0,
+ (LPSTR)&message, // NOT A BUG!
+ 0, NULL);
string result = message;
LocalFree(message);
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 4e2c9dcf..92c70c0d 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -106,6 +106,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
} // namespace
+void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
const ::google::protobuf::FileDescriptor* file =
@@ -588,6 +589,7 @@ inline void protobuf_AssignDescriptorsOnce() {
&protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto);
}
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
@@ -697,6 +699,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto() {
delete GeneratedCodeInfo_Annotation_reflection_;
}
+void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
static bool already_here = false;
if (already_here) return;
@@ -834,9 +837,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
".protobuf.GeneratedCodeInfo.Annotation\032O"
"\n\nAnnotation\022\020\n\004path\030\001 \003(\005B\002\020\001\022\023\n\013source"
"_file\030\002 \001(\t\022\r\n\005begin\030\003 \001(\005\022\013\n\003end\030\004 \001(\005B"
- "X\n\023com.google.protobufB\020DescriptorProtos"
- "H\001Z\ndescriptor\242\002\003GPB\252\002\032Google.Protobuf.R"
- "eflection", 5289);
+ "[\n\023com.google.protobufB\020DescriptorProtos"
+ "H\001Z\ndescriptor\240\001\001\242\002\003GPB\252\002\032Google.Protobu"
+ "f.Reflection", 5292);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -899,16 +902,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fdescriptor_2eproto {
}
} static_descriptor_initializer_google_2fprotobuf_2fdescriptor_2eproto_;
-namespace {
-
-static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
-static void MergeFromFail(int line) {
- GOOGLE_CHECK(false) << __FILE__ << ":" << line;
-}
-
-} // namespace
-
-
// ===================================================================
#if !defined(_MSC_VER) || _MSC_VER >= 1900
@@ -1088,7 +1081,9 @@ int FileDescriptorSet::ByteSize() const {
void FileDescriptorSet::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileDescriptorSet)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const FileDescriptorSet* source =
::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorSet>(
&from);
@@ -1103,7 +1098,9 @@ void FileDescriptorSet::MergeFrom(const ::google::protobuf::Message& from) {
void FileDescriptorSet::MergeFrom(const FileDescriptorSet& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorSet)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
file_.MergeFrom(from.file_);
if (from._internal_metadata_.have_unknown_fields()) {
mutable_unknown_fields()->MergeFrom(from.unknown_fields());
@@ -1856,7 +1853,9 @@ int FileDescriptorProto::ByteSize() const {
void FileDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileDescriptorProto)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const FileDescriptorProto* source =
::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorProto>(
&from);
@@ -1871,7 +1870,9 @@ void FileDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorProto)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
dependency_.MergeFrom(from.dependency_);
public_dependency_.MergeFrom(from.public_dependency_);
weak_dependency_.MergeFrom(from.weak_dependency_);
@@ -2532,7 +2533,7 @@ void DescriptorProto_ExtensionRange::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -2682,7 +2683,9 @@ int DescriptorProto_ExtensionRange::ByteSize() const {
void DescriptorProto_ExtensionRange::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto.ExtensionRange)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const DescriptorProto_ExtensionRange* source =
::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto_ExtensionRange>(
&from);
@@ -2697,7 +2700,9 @@ void DescriptorProto_ExtensionRange::MergeFrom(const ::google::protobuf::Message
void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRange& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ExtensionRange)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_start()) {
set_start(from.start());
@@ -2831,7 +2836,7 @@ void DescriptorProto_ReservedRange::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -2981,7 +2986,9 @@ int DescriptorProto_ReservedRange::ByteSize() const {
void DescriptorProto_ReservedRange::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto.ReservedRange)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const DescriptorProto_ReservedRange* source =
::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto_ReservedRange>(
&from);
@@ -2996,7 +3003,9 @@ void DescriptorProto_ReservedRange::MergeFrom(const ::google::protobuf::Message&
void DescriptorProto_ReservedRange::MergeFrom(const DescriptorProto_ReservedRange& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ReservedRange)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_start()) {
set_start(from.start());
@@ -3608,7 +3617,9 @@ int DescriptorProto::ByteSize() const {
void DescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const DescriptorProto* source =
::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto>(
&from);
@@ -3623,7 +3634,9 @@ void DescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
void DescriptorProto::MergeFrom(const DescriptorProto& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
field_.MergeFrom(from.field_);
extension_.MergeFrom(from.extension_);
nested_type_.MergeFrom(from.nested_type_);
@@ -4844,7 +4857,9 @@ int FieldDescriptorProto::ByteSize() const {
void FieldDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldDescriptorProto)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const FieldDescriptorProto* source =
::google::protobuf::internal::DynamicCastToGenerated<const FieldDescriptorProto>(
&from);
@@ -4859,7 +4874,9 @@ void FieldDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldDescriptorProto)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name()) {
set_has_name();
@@ -5606,7 +5623,9 @@ int OneofDescriptorProto::ByteSize() const {
void OneofDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.OneofDescriptorProto)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const OneofDescriptorProto* source =
::google::protobuf::internal::DynamicCastToGenerated<const OneofDescriptorProto>(
&from);
@@ -5621,7 +5640,9 @@ void OneofDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
void OneofDescriptorProto::MergeFrom(const OneofDescriptorProto& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.OneofDescriptorProto)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name()) {
set_has_name();
@@ -6056,7 +6077,9 @@ int EnumDescriptorProto::ByteSize() const {
void EnumDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumDescriptorProto)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const EnumDescriptorProto* source =
::google::protobuf::internal::DynamicCastToGenerated<const EnumDescriptorProto>(
&from);
@@ -6071,7 +6094,9 @@ void EnumDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
void EnumDescriptorProto::MergeFrom(const EnumDescriptorProto& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumDescriptorProto)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
value_.MergeFrom(from.value_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name()) {
@@ -6534,7 +6559,9 @@ int EnumValueDescriptorProto::ByteSize() const {
void EnumValueDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValueDescriptorProto)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const EnumValueDescriptorProto* source =
::google::protobuf::internal::DynamicCastToGenerated<const EnumValueDescriptorProto>(
&from);
@@ -6549,7 +6576,9 @@ void EnumValueDescriptorProto::MergeFrom(const ::google::protobuf::Message& from
void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueDescriptorProto)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name()) {
set_has_name();
@@ -7012,7 +7041,9 @@ int ServiceDescriptorProto::ByteSize() const {
void ServiceDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ServiceDescriptorProto)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const ServiceDescriptorProto* source =
::google::protobuf::internal::DynamicCastToGenerated<const ServiceDescriptorProto>(
&from);
@@ -7027,7 +7058,9 @@ void ServiceDescriptorProto::MergeFrom(const ::google::protobuf::Message& from)
void ServiceDescriptorProto::MergeFrom(const ServiceDescriptorProto& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceDescriptorProto)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
method_.MergeFrom(from.method_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name()) {
@@ -7314,7 +7347,7 @@ void MethodDescriptorProto::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -7642,7 +7675,9 @@ int MethodDescriptorProto::ByteSize() const {
void MethodDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MethodDescriptorProto)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const MethodDescriptorProto* source =
::google::protobuf::internal::DynamicCastToGenerated<const MethodDescriptorProto>(
&from);
@@ -7657,7 +7692,9 @@ void MethodDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodDescriptorProto)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name()) {
set_has_name();
@@ -8126,7 +8163,7 @@ void FileOptions::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -8792,7 +8829,9 @@ int FileOptions::ByteSize() const {
void FileOptions::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileOptions)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const FileOptions* source =
::google::protobuf::internal::DynamicCastToGenerated<const FileOptions>(
&from);
@@ -8807,7 +8846,9 @@ void FileOptions::MergeFrom(const ::google::protobuf::Message& from) {
void FileOptions::MergeFrom(const FileOptions& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileOptions)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_java_package()) {
@@ -9529,7 +9570,7 @@ void MessageOptions::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -9789,7 +9830,9 @@ int MessageOptions::ByteSize() const {
void MessageOptions::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MessageOptions)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const MessageOptions* source =
::google::protobuf::internal::DynamicCastToGenerated<const MessageOptions>(
&from);
@@ -9804,7 +9847,9 @@ void MessageOptions::MergeFrom(const ::google::protobuf::Message& from) {
void MessageOptions::MergeFrom(const MessageOptions& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MessageOptions)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_message_set_wire_format()) {
@@ -10138,7 +10183,7 @@ void FieldOptions::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -10477,7 +10522,9 @@ int FieldOptions::ByteSize() const {
void FieldOptions::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldOptions)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const FieldOptions* source =
::google::protobuf::internal::DynamicCastToGenerated<const FieldOptions>(
&from);
@@ -10492,7 +10539,9 @@ void FieldOptions::MergeFrom(const ::google::protobuf::Message& from) {
void FieldOptions::MergeFrom(const FieldOptions& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldOptions)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_ctype()) {
@@ -10943,7 +10992,9 @@ int OneofOptions::ByteSize() const {
void OneofOptions::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.OneofOptions)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const OneofOptions* source =
::google::protobuf::internal::DynamicCastToGenerated<const OneofOptions>(
&from);
@@ -10958,7 +11009,9 @@ void OneofOptions::MergeFrom(const ::google::protobuf::Message& from) {
void OneofOptions::MergeFrom(const OneofOptions& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.OneofOptions)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
_extensions_.MergeFrom(from._extensions_);
if (from._internal_metadata_.have_unknown_fields()) {
@@ -11124,7 +11177,7 @@ void EnumOptions::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -11324,7 +11377,9 @@ int EnumOptions::ByteSize() const {
void EnumOptions::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumOptions)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const EnumOptions* source =
::google::protobuf::internal::DynamicCastToGenerated<const EnumOptions>(
&from);
@@ -11339,7 +11394,9 @@ void EnumOptions::MergeFrom(const ::google::protobuf::Message& from) {
void EnumOptions::MergeFrom(const EnumOptions& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumOptions)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_allow_alias()) {
@@ -11709,7 +11766,9 @@ int EnumValueOptions::ByteSize() const {
void EnumValueOptions::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValueOptions)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const EnumValueOptions* source =
::google::protobuf::internal::DynamicCastToGenerated<const EnumValueOptions>(
&from);
@@ -11724,7 +11783,9 @@ void EnumValueOptions::MergeFrom(const ::google::protobuf::Message& from) {
void EnumValueOptions::MergeFrom(const EnumValueOptions& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueOptions)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_deprecated()) {
@@ -12066,7 +12127,9 @@ int ServiceOptions::ByteSize() const {
void ServiceOptions::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ServiceOptions)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const ServiceOptions* source =
::google::protobuf::internal::DynamicCastToGenerated<const ServiceOptions>(
&from);
@@ -12081,7 +12144,9 @@ void ServiceOptions::MergeFrom(const ::google::protobuf::Message& from) {
void ServiceOptions::MergeFrom(const ServiceOptions& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceOptions)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_deprecated()) {
@@ -12423,7 +12488,9 @@ int MethodOptions::ByteSize() const {
void MethodOptions::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MethodOptions)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const MethodOptions* source =
::google::protobuf::internal::DynamicCastToGenerated<const MethodOptions>(
&from);
@@ -12438,7 +12505,9 @@ void MethodOptions::MergeFrom(const ::google::protobuf::Message& from) {
void MethodOptions::MergeFrom(const MethodOptions& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodOptions)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_deprecated()) {
@@ -12796,7 +12865,9 @@ int UninterpretedOption_NamePart::ByteSize() const {
void UninterpretedOption_NamePart::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UninterpretedOption.NamePart)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const UninterpretedOption_NamePart* source =
::google::protobuf::internal::DynamicCastToGenerated<const UninterpretedOption_NamePart>(
&from);
@@ -12811,7 +12882,9 @@ void UninterpretedOption_NamePart::MergeFrom(const ::google::protobuf::Message&
void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption.NamePart)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name_part()) {
set_has_name_part();
@@ -12960,7 +13033,7 @@ void UninterpretedOption::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -13313,7 +13386,9 @@ int UninterpretedOption::ByteSize() const {
void UninterpretedOption::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UninterpretedOption)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const UninterpretedOption* source =
::google::protobuf::internal::DynamicCastToGenerated<const UninterpretedOption>(
&from);
@@ -13328,7 +13403,9 @@ void UninterpretedOption::MergeFrom(const ::google::protobuf::Message& from) {
void UninterpretedOption::MergeFrom(const UninterpretedOption& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
name_.MergeFrom(from.name_);
if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
if (from.has_identifier_value()) {
@@ -14170,7 +14247,9 @@ int SourceCodeInfo_Location::ByteSize() const {
void SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceCodeInfo.Location)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const SourceCodeInfo_Location* source =
::google::protobuf::internal::DynamicCastToGenerated<const SourceCodeInfo_Location>(
&from);
@@ -14185,7 +14264,9 @@ void SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from)
void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo.Location)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
path_.MergeFrom(from.path_);
span_.MergeFrom(from.span_);
leading_detached_comments_.MergeFrom(from.leading_detached_comments_);
@@ -14426,7 +14507,9 @@ int SourceCodeInfo::ByteSize() const {
void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceCodeInfo)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const SourceCodeInfo* source =
::google::protobuf::internal::DynamicCastToGenerated<const SourceCodeInfo>(
&from);
@@ -14441,7 +14524,9 @@ void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) {
void SourceCodeInfo::MergeFrom(const SourceCodeInfo& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
location_.MergeFrom(from.location_);
if (from._internal_metadata_.have_unknown_fields()) {
mutable_unknown_fields()->MergeFrom(from.unknown_fields());
@@ -14833,7 +14918,7 @@ void GeneratedCodeInfo_Annotation::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -15093,7 +15178,9 @@ int GeneratedCodeInfo_Annotation::ByteSize() const {
void GeneratedCodeInfo_Annotation::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.GeneratedCodeInfo.Annotation)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const GeneratedCodeInfo_Annotation* source =
::google::protobuf::internal::DynamicCastToGenerated<const GeneratedCodeInfo_Annotation>(
&from);
@@ -15108,7 +15195,9 @@ void GeneratedCodeInfo_Annotation::MergeFrom(const ::google::protobuf::Message&
void GeneratedCodeInfo_Annotation::MergeFrom(const GeneratedCodeInfo_Annotation& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo.Annotation)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
path_.MergeFrom(from.path_);
if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
if (from.has_source_file()) {
@@ -15348,7 +15437,9 @@ int GeneratedCodeInfo::ByteSize() const {
void GeneratedCodeInfo::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.GeneratedCodeInfo)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const GeneratedCodeInfo* source =
::google::protobuf::internal::DynamicCastToGenerated<const GeneratedCodeInfo>(
&from);
@@ -15363,7 +15454,9 @@ void GeneratedCodeInfo::MergeFrom(const ::google::protobuf::Message& from) {
void GeneratedCodeInfo::MergeFrom(const GeneratedCodeInfo& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
annotation_.MergeFrom(from.annotation_);
if (from._internal_metadata_.have_unknown_fields()) {
mutable_unknown_fields()->MergeFrom(from.unknown_fields());
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index da853dbc..28410d4a 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -45,6 +45,7 @@ option java_package = "com.google.protobuf";
option java_outer_classname = "DescriptorProtos";
option csharp_namespace = "Google.Protobuf.Reflection";
option objc_class_prefix = "GPB";
+option java_generate_equals_and_hash = true;
// descriptor.proto must be optimized for speed because reflection-based
// algorithms don't work during bootstrapping.
diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc
index b0c641bf..ed5cca4b 100644
--- a/src/google/protobuf/duration.pb.cc
+++ b/src/google/protobuf/duration.pb.cc
@@ -29,6 +29,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
} // namespace
+void protobuf_AssignDesc_google_2fprotobuf_2fduration_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AssignDesc_google_2fprotobuf_2fduration_2eproto() {
protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto();
const ::google::protobuf::FileDescriptor* file =
@@ -61,6 +62,7 @@ inline void protobuf_AssignDescriptorsOnce() {
&protobuf_AssignDesc_google_2fprotobuf_2fduration_2eproto);
}
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
@@ -74,6 +76,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fduration_2eproto() {
delete Duration_reflection_;
}
+void protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto() {
static bool already_here = false;
if (already_here) return;
@@ -101,16 +104,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fduration_2eproto {
}
} static_descriptor_initializer_google_2fprotobuf_2fduration_2eproto_;
-namespace {
-
-static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
-static void MergeFromFail(int line) {
- GOOGLE_CHECK(false) << __FILE__ << ":" << line;
-}
-
-} // namespace
-
-
// ===================================================================
#if !defined(_MSC_VER) || _MSC_VER >= 1900
@@ -192,7 +185,7 @@ void Duration::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -322,7 +315,9 @@ int Duration::ByteSize() const {
void Duration::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Duration)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const Duration* source =
::google::protobuf::internal::DynamicCastToGenerated<const Duration>(
&from);
@@ -337,7 +332,9 @@ void Duration::MergeFrom(const ::google::protobuf::Message& from) {
void Duration::MergeFrom(const Duration& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Duration)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.seconds() != 0) {
set_seconds(from.seconds());
}
diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc
index 8b461201..83775753 100644
--- a/src/google/protobuf/empty.pb.cc
+++ b/src/google/protobuf/empty.pb.cc
@@ -29,6 +29,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
} // namespace
+void protobuf_AssignDesc_google_2fprotobuf_2fempty_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AssignDesc_google_2fprotobuf_2fempty_2eproto() {
protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto();
const ::google::protobuf::FileDescriptor* file =
@@ -59,6 +60,7 @@ inline void protobuf_AssignDescriptorsOnce() {
&protobuf_AssignDesc_google_2fprotobuf_2fempty_2eproto);
}
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
@@ -72,6 +74,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fempty_2eproto() {
delete Empty_reflection_;
}
+void protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto() {
static bool already_here = false;
if (already_here) return;
@@ -98,16 +101,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fempty_2eproto {
}
} static_descriptor_initializer_google_2fprotobuf_2fempty_2eproto_;
-namespace {
-
-static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
-static void MergeFromFail(int line) {
- GOOGLE_CHECK(false) << __FILE__ << ":" << line;
-}
-
-} // namespace
-
-
// ===================================================================
#if !defined(_MSC_VER) || _MSC_VER >= 1900
@@ -240,7 +233,9 @@ int Empty::ByteSize() const {
void Empty::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Empty)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const Empty* source =
::google::protobuf::internal::DynamicCastToGenerated<const Empty>(
&from);
@@ -255,7 +250,9 @@ void Empty::MergeFrom(const ::google::protobuf::Message& from) {
void Empty::MergeFrom(const Empty& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Empty)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
}
void Empty::CopyFrom(const ::google::protobuf::Message& from) {
diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc
index 5dd171ed..b26a246c 100644
--- a/src/google/protobuf/extension_set_heavy.cc
+++ b/src/google/protobuf/extension_set_heavy.cc
@@ -341,7 +341,7 @@ bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
int ExtensionSet::SpaceUsedExcludingSelf() const {
int total_size =
- extensions_.size() * sizeof(map<int, Extension>::value_type);
+ extensions_.size() * sizeof(ExtensionMap::value_type);
for (ExtensionMap::const_iterator iter = extensions_.begin(),
end = extensions_.end();
iter != end;
diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc
index d197b406..ed05fe57 100644
--- a/src/google/protobuf/field_mask.pb.cc
+++ b/src/google/protobuf/field_mask.pb.cc
@@ -29,6 +29,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
} // namespace
+void protobuf_AssignDesc_google_2fprotobuf_2ffield_5fmask_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AssignDesc_google_2fprotobuf_2ffield_5fmask_2eproto() {
protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto();
const ::google::protobuf::FileDescriptor* file =
@@ -60,6 +61,7 @@ inline void protobuf_AssignDescriptorsOnce() {
&protobuf_AssignDesc_google_2fprotobuf_2ffield_5fmask_2eproto);
}
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
@@ -73,6 +75,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2ffield_5fmask_2eproto() {
delete FieldMask_reflection_;
}
+void protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto() {
static bool already_here = false;
if (already_here) return;
@@ -99,16 +102,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2ffield_5fmask_2eproto {
}
} static_descriptor_initializer_google_2fprotobuf_2ffield_5fmask_2eproto_;
-namespace {
-
-static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
-static void MergeFromFail(int line) {
- GOOGLE_CHECK(false) << __FILE__ << ":" << line;
-}
-
-} // namespace
-
-
// ===================================================================
#if !defined(_MSC_VER) || _MSC_VER >= 1900
@@ -281,7 +274,9 @@ int FieldMask::ByteSize() const {
void FieldMask::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldMask)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const FieldMask* source =
::google::protobuf::internal::DynamicCastToGenerated<const FieldMask>(
&from);
@@ -296,7 +291,9 @@ void FieldMask::MergeFrom(const ::google::protobuf::Message& from) {
void FieldMask::MergeFrom(const FieldMask& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldMask)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
paths_.MergeFrom(from.paths_);
}
diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc
index 7b813f8a..7ad6d61c 100644
--- a/src/google/protobuf/generated_message_util.cc
+++ b/src/google/protobuf/generated_message_util.cc
@@ -73,6 +73,12 @@ int StringSpaceUsedExcludingSelf(const string& str) {
+void MergeFromFail(const char* file, int line) {
+ GOOGLE_CHECK(false) << file << ":" << line;
+ // Open-source GOOGLE_CHECK(false) is not NORETURN.
+ exit(1);
+}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
index 56f5afd2..8967726e 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/src/google/protobuf/generated_message_util.h
@@ -41,8 +41,8 @@
#include <assert.h>
#include <string>
-#include <google/protobuf/stubs/once.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
namespace google {
@@ -112,8 +112,13 @@ class ArenaString;
// pointer to a copy of the string that resides in *arena. Requires both
// args to be non-NULL. If something goes wrong while reading the data
// then NULL is returned (e.g., input does not start with a valid varint).
-ArenaString* ReadArenaString(::google::protobuf::io::CodedInputStream* input,
- ::google::protobuf::Arena* arena);
+LIBPROTOBUF_EXPORT ArenaString* ReadArenaString(
+ ::google::protobuf::io::CodedInputStream* input,
+ ::google::protobuf::Arena* arena);
+
+// Helper function to crash on merge failure.
+// Moved out of generated code to reduce binary size.
+LIBPROTOBUF_EXPORT void MergeFromFail(const char* file, int line) GOOGLE_ATTRIBUTE_NORETURN;
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index 148eee0e..a5675e79 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -649,13 +649,16 @@ bool CodedInputStream::Refresh() {
// CodedOutputStream =================================================
+bool CodedOutputStream::default_serialization_deterministic_ = false;
+
CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output)
: output_(output),
buffer_(NULL),
buffer_size_(0),
total_bytes_(0),
had_error_(false),
- aliasing_enabled_(false) {
+ aliasing_enabled_(false),
+ serialization_deterministic_is_overridden_(false) {
// Eagerly Refresh() so buffer space is immediately available.
Refresh();
// The Refresh() may have failed. If the client doesn't write any data,
@@ -671,7 +674,8 @@ CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output,
buffer_size_(0),
total_bytes_(0),
had_error_(false),
- aliasing_enabled_(false) {
+ aliasing_enabled_(false),
+ serialization_deterministic_is_overridden_(false) {
if (do_eager_refresh) {
// Eagerly Refresh() so buffer space is immediately available.
Refresh();
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index eb320745..316da765 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -813,6 +813,44 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// created.
bool HadError() const { return had_error_; }
+ // Deterministic serialization, if requested, guarantees that for a given
+ // binary, equal messages will always be serialized to the same bytes. This
+ // implies:
+ // . repeated serialization of a message will return the same bytes
+ // . different processes of the same binary (which may be executing on
+ // different machines) will serialize equal messages to the same bytes.
+ //
+ // Note the deterministic serialization is NOT canonical across languages; it
+ // is also unstable across different builds with schema changes due to unknown
+ // fields. Users who need canonical serialization, e.g., persistent storage in
+ // a canonical form, fingerprinting, etc., should define their own
+ // canonicalization specification and implement the serializer using
+ // reflection APIs rather than relying on this API.
+ //
+ // If determinisitc serialization is requested, the serializer will
+ // sort map entries by keys in lexicographical order or numerical order.
+ // (This is an implementation detail and may subject to change.)
+ //
+ // There are two ways to determine whether serialization should be
+ // deterministic for this CodedOutputStream. If SetSerializationDeterministic
+ // has not yet been called, then the default comes from the global default,
+ // which is false, until SetDefaultSerializationDeterministic has been called.
+ // Otherwise, SetSerializationDeterministic has been called, and the last
+ // value passed to it is all that matters.
+ void SetSerializationDeterministic(bool value) {
+ serialization_deterministic_is_overridden_ = true;
+ serialization_deterministic_override_ = value;
+ }
+ // See above. Also, note that users of this CodedOutputStream may need to
+ // call IsSerializationDeterminstic() to serialize in the intended way. This
+ // CodedOutputStream cannot enforce a desire for deterministic serialization
+ // by itself.
+ bool IsSerializationDeterminstic() const {
+ return serialization_deterministic_is_overridden_ ?
+ serialization_deterministic_override_ :
+ default_serialization_deterministic_;
+ }
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedOutputStream);
@@ -822,6 +860,10 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
int total_bytes_; // Sum of sizes of all buffers seen so far.
bool had_error_; // Whether an error occurred during output.
bool aliasing_enabled_; // See EnableAliasing().
+ // See SetSerializationDeterministic() regarding these three fields.
+ bool serialization_deterministic_is_overridden_;
+ bool serialization_deterministic_override_;
+ static bool default_serialization_deterministic_;
// Advance the buffer by a given number of bytes.
void Advance(int amount);
@@ -849,6 +891,11 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
uint64 value, uint8* target);
static int VarintSize32Fallback(uint32 value);
+
+ // See above. Other projects may use "friend" to allow them to call this.
+ static void SetDefaultSerializationDeterministic() {
+ default_serialization_deterministic_ = true;
+ }
};
// inline methods ====================================================
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index 42bcfd94..1b9aa703 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -1250,7 +1250,7 @@ class Map {
// Return whether table_[b] is a linked list that seems awfully long.
// Requires table_[b] to point to a non-empty linked list.
bool TableEntryIsTooLong(size_type b) {
- const int kMaxLength = 8;
+ const size_type kMaxLength = 8;
size_type count = 0;
Node* node = static_cast<Node*>(table_[b]);
do {
diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h
index 23ac7b8a..4dedfd57 100644
--- a/src/google/protobuf/map_entry_lite.h
+++ b/src/google/protobuf/map_entry_lite.h
@@ -535,6 +535,32 @@ class MapEntryLite : public MessageLite {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
};
+// Helpers for deterministic serialization =============================
+
+// This struct can be used with any generic sorting algorithm. If the Key
+// type is relatively small and easy to copy then copying Keys into an
+// array of SortItems can be beneficial. Then all the data the sorting
+// algorithm needs to touch is in that one array.
+template <typename Key, typename PtrToKeyValuePair> struct SortItem {
+ SortItem() {}
+ explicit SortItem(PtrToKeyValuePair p) : first(p->first), second(p) {}
+
+ Key first;
+ PtrToKeyValuePair second;
+};
+
+template <typename T> struct CompareByFirstField {
+ bool operator()(const T& a, const T& b) const {
+ return a.first < b.first;
+ }
+};
+
+template <typename T> struct CompareByDerefFirst {
+ bool operator()(const T& a, const T& b) const {
+ return a->first < b->first;
+ }
+};
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/map_proto2_unittest.proto b/src/google/protobuf/map_proto2_unittest.proto
index 916cc546..ddc2a582 100644
--- a/src/google/protobuf/map_proto2_unittest.proto
+++ b/src/google/protobuf/map_proto2_unittest.proto
@@ -64,3 +64,23 @@ message TestEnumMapPlusExtra {
message TestImportEnumMap {
map<int32, protobuf_unittest_import.ImportEnumForMap> import_enum_amp = 1;
}
+
+message TestIntIntMap {
+ map<int32, int32> m = 1;
+}
+
+// Test all key types: string, plus the non-floating-point scalars.
+message TestMaps {
+ map<int32, TestIntIntMap> m_int32 = 1;
+ map<int64, TestIntIntMap> m_int64 = 2;
+ map<uint32, TestIntIntMap> m_uint32 = 3;
+ map<uint64, TestIntIntMap> m_uint64 = 4;
+ map<sint32, TestIntIntMap> m_sint32 = 5;
+ map<sint64, TestIntIntMap> m_sint64 = 6;
+ map<fixed32, TestIntIntMap> m_fixed32 = 7;
+ map<fixed64, TestIntIntMap> m_fixed64 = 8;
+ map<sfixed32, TestIntIntMap> m_sfixed32 = 9;
+ map<sfixed64, TestIntIntMap> m_sfixed64 = 10;
+ map<bool, TestIntIntMap> m_bool = 11;
+ map<string, TestIntIntMap> m_string = 12;
+}
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index cdd1ccd5..03954e75 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -74,6 +74,7 @@
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/util/time_util.h>
+#include <google/protobuf/util/message_differencer.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <gmock/gmock.h>
@@ -2869,6 +2870,82 @@ TEST(WireFormatForMapFieldTest, MapParseHelpers) {
}
}
+// Deterministic Serialization Test ==========================================
+
+template <typename T>
+static string DeterministicSerialization(const T& t) {
+ const int size = t.ByteSize();
+ string result(size, '\0');
+ io::ArrayOutputStream array_stream(string_as_array(&result), size);
+ io::CodedOutputStream output_stream(&array_stream);
+ output_stream.SetSerializationDeterministic(true);
+ t.SerializeWithCachedSizes(&output_stream);
+ EXPECT_FALSE(output_stream.HadError());
+ EXPECT_EQ(size, output_stream.ByteCount());
+ return result;
+}
+
+// Helper to test the serialization of the first arg against a golden file.
+static void TestDeterministicSerialization(const protobuf_unittest::TestMaps& t,
+ const string& filename) {
+ string expected;
+ GOOGLE_CHECK_OK(File::GetContents(
+ TestSourceDir() + "/google/protobuf/testdata/" + filename,
+ &expected, true));
+ const string actual = DeterministicSerialization(t);
+ EXPECT_EQ(expected, actual);
+ protobuf_unittest::TestMaps u;
+ EXPECT_TRUE(u.ParseFromString(actual));
+ EXPECT_TRUE(google::protobuf::util::MessageDifferencer::Equals(u, t));
+}
+
+// Helper for MapSerializationTest. Return a 7-bit ASCII string.
+static string ConstructKey(uint64 n) {
+ string s(n % static_cast<uint64>(9), '\0');
+ if (s.empty()) {
+ return StrCat(n);
+ } else {
+ while (n != 0) {
+ s[n % s.size()] = (n >> 10) & 0x7f;
+ n /= 888;
+ }
+ return s;
+ }
+}
+
+TEST(MapSerializationTest, Deterministic) {
+ const int kIters = 25;
+ protobuf_unittest::TestMaps t;
+ protobuf_unittest::TestIntIntMap inner;
+ (*inner.mutable_m())[0] = (*inner.mutable_m())[10] =
+ (*inner.mutable_m())[-200] = 0;
+ uint64 frog = 9;
+ const uint64 multiplier = 0xa29cd16f;
+ for (int i = 0; i < kIters; i++) {
+ const int32 i32 = static_cast<int32>(frog & 0xffffffff);
+ const uint32 u32 = static_cast<uint32>(i32) * 91919;
+ const int64 i64 = static_cast<int64>(frog);
+ const uint64 u64 = frog * static_cast<uint64>(187321);
+ const bool b = i32 > 0;
+ const string s = ConstructKey(frog);
+ (*inner.mutable_m())[i] = i32;
+ (*t.mutable_m_int32())[i32] = (*t.mutable_m_sint32())[i32] =
+ (*t.mutable_m_sfixed32())[i32] = inner;
+ (*t.mutable_m_uint32())[u32] = (*t.mutable_m_fixed32())[u32] = inner;
+ (*t.mutable_m_int64())[i64] = (*t.mutable_m_sint64())[i64] =
+ (*t.mutable_m_sfixed64())[i64] = inner;
+ (*t.mutable_m_uint64())[u64] = (*t.mutable_m_fixed64())[u64] = inner;
+ (*t.mutable_m_bool())[b] = inner;
+ (*t.mutable_m_string())[s] = inner;
+ (*t.mutable_m_string())[s + string(1 << (u32 % static_cast<uint32>(9)),
+ b)] = inner;
+ inner.mutable_m()->erase(i);
+ frog = frog * multiplier + i;
+ frog ^= (frog >> 41);
+ }
+ TestDeterministicSerialization(t, "golden_message_maps");
+}
+
// Text Format Test =================================================
TEST(TextFormatMapTest, SerializeAndParse) {
diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h
index 74e8bb50..685a770f 100644
--- a/src/google/protobuf/map_type_handler.h
+++ b/src/google/protobuf/map_type_handler.h
@@ -166,10 +166,10 @@ class MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type> {
io::CodedOutputStream* output);
static inline uint8* InternalWriteToArray(int field,
const MapEntryAccessorType& value,
- bool deterministic, uint8* output);
+ bool deterministic, uint8* target);
static inline uint8* WriteToArray(int field,
const MapEntryAccessorType& value,
- uint8* output);
+ uint8* target);
// Functions to manipulate data on memory. ========================
static inline const Type& GetExternalReference(const Type* value);
@@ -227,11 +227,11 @@ class MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type> {
int field, \
const MapEntryAccessorType& value, \
bool deterministic, \
- uint8* output); \
+ uint8* target); \
static inline uint8* WriteToArray(int field, \
const MapEntryAccessorType& value, \
- uint8* output) { \
- return InternalWriteToArray(field, value, false, output); \
+ uint8* target) { \
+ return InternalWriteToArray(field, value, false, target); \
} \
static inline const MapEntryAccessorType& GetExternalReference( \
const TypeOnMemory& value); \
@@ -374,9 +374,9 @@ template <typename Type>
inline uint8*
MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::InternalWriteToArray(
int field, const MapEntryAccessorType& value, bool deterministic,
- uint8* output) {
+ uint8* target) {
return WireFormatLite::InternalWriteMessageToArray(field, value,
- deterministic, output);
+ deterministic, target);
}
#define WRITE_METHOD(FieldType, DeclaredType) \
@@ -390,8 +390,8 @@ MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::InternalWriteToArray(
inline uint8* \
MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
Type>::InternalWriteToArray( \
- int field, const MapEntryAccessorType& value, bool, uint8* output) { \
- return WireFormatLite::Write##DeclaredType##ToArray(field, value, output); \
+ int field, const MapEntryAccessorType& value, bool, uint8* target) { \
+ return WireFormatLite::Write##DeclaredType##ToArray(field, value, target); \
}
WRITE_METHOD(STRING , String)
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index d62ca79c..f18077dd 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -62,8 +62,6 @@ namespace protobuf {
using internal::WireFormat;
using internal::ReflectionOps;
-Message::~Message() {}
-
void Message::MergeFrom(const Message& from) {
const Descriptor* descriptor = GetDescriptor();
GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index dcdffe1c..9705e97e 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -179,7 +179,7 @@ struct Metadata {
class LIBPROTOBUF_EXPORT Message : public MessageLite {
public:
inline Message() {}
- virtual ~Message();
+ virtual ~Message() {}
// Basic Operations ------------------------------------------------
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index 3913be1b..ba56db95 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -46,8 +46,6 @@
namespace google {
namespace protobuf {
-MessageLite::~MessageLite() {}
-
string MessageLite::InitializationErrorString() const {
return "(cannot determine missing fields for lite message)";
}
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
index f606aeec..2bdfe496 100644
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -81,7 +81,7 @@ namespace internal {
class LIBPROTOBUF_EXPORT MessageLite {
public:
inline MessageLite() {}
- virtual ~MessageLite();
+ virtual ~MessageLite() {}
// Basic Operations ------------------------------------------------
diff --git a/src/google/protobuf/repeated_field_reflection.h b/src/google/protobuf/repeated_field_reflection.h
deleted file mode 100644
index 512c0f1d..00000000
--- a/src/google/protobuf/repeated_field_reflection.h
+++ /dev/null
@@ -1,337 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This header file is protobuf internal. Users should not include this
-// file directly.
-#ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_REFLECTION_H__
-#define GOOGLE_PROTOBUF_REPEATED_FIELD_REFLECTION_H__
-
-#include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
-
-#include <google/protobuf/generated_enum_reflection.h>
-
-namespace google {
-namespace protobuf {
-namespace internal {
-// Interfaces used to implement reflection RepeatedFieldRef API.
-// Reflection::GetRepeatedAccessor() should return a pointer to an singleton
-// object that implements the below interface.
-//
-// This interface passes/returns values using void pointers. The actual type
-// of the value depends on the field's cpp_type. Following is a mapping from
-// cpp_type to the type that should be used in this interface:
-//
-// field->cpp_type() T Actual type of void*
-// CPPTYPE_INT32 int32 int32
-// CPPTYPE_UINT32 uint32 uint32
-// CPPTYPE_INT64 int64 int64
-// CPPTYPE_UINT64 uint64 uint64
-// CPPTYPE_DOUBLE double double
-// CPPTYPE_FLOAT float float
-// CPPTYPE_BOOL bool bool
-// CPPTYPE_ENUM generated enum type int32
-// CPPTYPE_STRING string string
-// CPPTYPE_MESSAGE generated message type google::protobuf::Message
-// or google::protobuf::Message
-//
-// Note that for enums we use int32 in the interface.
-//
-// You can map from T to the actual type using RefTypeTraits:
-// typedef RefTypeTraits<T>::AccessorValueType ActualType;
-class LIBPROTOBUF_EXPORT RepeatedFieldAccessor {
- public:
- // Typedefs for clarity.
- typedef void Field;
- typedef void Value;
- typedef void Iterator;
-
- virtual ~RepeatedFieldAccessor();
- virtual bool IsEmpty(const Field* data) const = 0;
- virtual int Size(const Field* data) const = 0;
- // Depends on the underlying representation of the repeated field, this
- // method can return a pointer to the underlying object if such an object
- // exists, or fill the data into scratch_space and return scratch_space.
- // Callers of this method must ensure scratch_space is a valid pointer
- // to a mutable object of the correct type.
- virtual const Value* Get(
- const Field* data, int index, Value* scratch_space) const = 0;
-
- virtual void Clear(Field* data) const = 0;
- virtual void Set(Field* data, int index, const Value* value) const = 0;
- virtual void Add(Field* data, const Value* value) const = 0;
- virtual void RemoveLast(Field* data) const = 0;
- virtual void SwapElements(Field* data, int index1, int index2) const = 0;
- virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator,
- Field* other_data) const = 0;
-
- // Create an iterator that points at the beginning of the repeated field.
- virtual Iterator* BeginIterator(const Field* data) const = 0;
- // Create an iterator that points at the end of the repeated field.
- virtual Iterator* EndIterator(const Field* data) const = 0;
- // Make a copy of an iterator and return the new copy.
- virtual Iterator* CopyIterator(const Field* data,
- const Iterator* iterator) const = 0;
- // Move an iterator to point to the next element.
- virtual Iterator* AdvanceIterator(const Field* data,
- Iterator* iterator) const = 0;
- // Compare whether two iterators point to the same element.
- virtual bool EqualsIterator(const Field* data, const Iterator* a,
- const Iterator* b) const = 0;
- // Delete an iterator created by BeginIterator(), EndIterator() and
- // CopyIterator().
- virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0;
- // Like Get() but for iterators.
- virtual const Value* GetIteratorValue(const Field* data,
- const Iterator* iterator,
- Value* scratch_space) const = 0;
-
- // Templated methods that make using this interface easier for non-message
- // types.
- template<typename T>
- T Get(const Field* data, int index) const {
- typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
- ActualType scratch_space;
- return static_cast<T>(
- *reinterpret_cast<const ActualType*>(
- Get(data, index, static_cast<Value*>(&scratch_space))));
- }
-
- template<typename T, typename ValueType>
- void Set(Field* data, int index, const ValueType& value) const {
- typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
- // In this RepeatedFieldAccessor interface we pass/return data using
- // raw pointers. Type of the data these raw pointers point to should
- // be ActualType. Here we have a ValueType object and want a ActualType
- // pointer. We can't cast a ValueType pointer to an ActualType pointer
- // directly because their type might be different (for enums ValueType
- // may be a generated enum type while ActualType is int32). To be safe
- // we make a copy to get a temporary ActualType object and use it.
- ActualType tmp = static_cast<ActualType>(value);
- Set(data, index, static_cast<const Value*>(&tmp));
- }
-
- template<typename T, typename ValueType>
- void Add(Field* data, const ValueType& value) const {
- typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
- // In this RepeatedFieldAccessor interface we pass/return data using
- // raw pointers. Type of the data these raw pointers point to should
- // be ActualType. Here we have a ValueType object and want a ActualType
- // pointer. We can't cast a ValueType pointer to an ActualType pointer
- // directly because their type might be different (for enums ValueType
- // may be a generated enum type while ActualType is int32). To be safe
- // we make a copy to get a temporary ActualType object and use it.
- ActualType tmp = static_cast<ActualType>(value);
- Add(data, static_cast<const Value*>(&tmp));
- }
-};
-
-// Implement (Mutable)RepeatedFieldRef::iterator
-template<typename T>
-class RepeatedFieldRefIterator
- : public std::iterator<std::forward_iterator_tag, T> {
- typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
- typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
- typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;
-
- public:
- // Constructor for non-message fields.
- RepeatedFieldRefIterator(const void* data,
- const RepeatedFieldAccessor* accessor,
- bool begin)
- : data_(data), accessor_(accessor),
- iterator_(begin ? accessor->BeginIterator(data) :
- accessor->EndIterator(data)),
- scratch_space_(new AccessorValueType) {
- }
- // Constructor for message fields.
- RepeatedFieldRefIterator(const void* data,
- const RepeatedFieldAccessor* accessor,
- bool begin,
- AccessorValueType* scratch_space)
- : data_(data), accessor_(accessor),
- iterator_(begin ? accessor->BeginIterator(data) :
- accessor->EndIterator(data)),
- scratch_space_(scratch_space) {
- }
- ~RepeatedFieldRefIterator() {
- accessor_->DeleteIterator(data_, iterator_);
- }
- RepeatedFieldRefIterator operator++(int) {
- RepeatedFieldRefIterator tmp(*this);
- iterator_ = accessor_->AdvanceIterator(data_, iterator_);
- return tmp;
- }
- RepeatedFieldRefIterator& operator++() {
- iterator_ = accessor_->AdvanceIterator(data_, iterator_);
- return *this;
- }
- IteratorValueType operator*() const {
- return static_cast<IteratorValueType>(
- *static_cast<const AccessorValueType*>(
- accessor_->GetIteratorValue(
- data_, iterator_, scratch_space_.get())));
- }
- IteratorPointerType operator->() const {
- return static_cast<IteratorPointerType>(
- accessor_->GetIteratorValue(
- data_, iterator_, scratch_space_.get()));
- }
- bool operator!=(const RepeatedFieldRefIterator& other) const {
- assert(data_ == other.data_);
- assert(accessor_ == other.accessor_);
- return !accessor_->EqualsIterator(data_, iterator_, other.iterator_);
- }
- bool operator==(const RepeatedFieldRefIterator& other) const {
- return !this->operator!=(other);
- }
-
- RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other)
- : data_(other.data_), accessor_(other.accessor_),
- iterator_(accessor_->CopyIterator(data_, other.iterator_)) {
- }
- RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) {
- if (this != &other) {
- accessor_->DeleteIterator(data_, iterator_);
- data_ = other.data_;
- accessor_ = other.accessor_;
- iterator_ = accessor_->CopyIterator(data_, other.iterator_);
- }
- return *this;
- }
-
- protected:
- const void* data_;
- const RepeatedFieldAccessor* accessor_;
- void* iterator_;
- google::protobuf::scoped_ptr<AccessorValueType> scratch_space_;
-};
-
-// TypeTraits that maps the type parameter T of RepeatedFieldRef or
-// MutableRepeatedFieldRef to corresponding iterator type,
-// RepeatedFieldAccessor type, etc.
-template<typename T>
-struct PrimitiveTraits {
- static const bool is_primitive = false;
-};
-#define DEFINE_PRIMITIVE(TYPE, type) \
- template<> struct PrimitiveTraits<type> { \
- static const bool is_primitive = true; \
- static const FieldDescriptor::CppType cpp_type = \
- FieldDescriptor::CPPTYPE_ ## TYPE; \
- };
-DEFINE_PRIMITIVE(INT32, int32)
-DEFINE_PRIMITIVE(UINT32, uint32)
-DEFINE_PRIMITIVE(INT64, int64)
-DEFINE_PRIMITIVE(UINT64, uint64)
-DEFINE_PRIMITIVE(FLOAT, float)
-DEFINE_PRIMITIVE(DOUBLE, double)
-DEFINE_PRIMITIVE(BOOL, bool)
-#undef DEFINE_PRIMITIVE
-
-template<typename T>
-struct RefTypeTraits<
- T, typename internal::enable_if<PrimitiveTraits<T>::is_primitive>::type> {
- typedef RepeatedFieldRefIterator<T> iterator;
- typedef RepeatedFieldAccessor AccessorType;
- typedef T AccessorValueType;
- typedef T IteratorValueType;
- typedef T* IteratorPointerType;
- static const FieldDescriptor::CppType cpp_type =
- PrimitiveTraits<T>::cpp_type;
- static const Descriptor* GetMessageFieldDescriptor() {
- return NULL;
- }
-};
-
-template<typename T>
-struct RefTypeTraits<
- T, typename internal::enable_if<is_proto_enum<T>::value>::type> {
- typedef RepeatedFieldRefIterator<T> iterator;
- typedef RepeatedFieldAccessor AccessorType;
- // We use int32 for repeated enums in RepeatedFieldAccessor.
- typedef int32 AccessorValueType;
- typedef T IteratorValueType;
- typedef int32* IteratorPointerType;
- static const FieldDescriptor::CppType cpp_type =
- FieldDescriptor::CPPTYPE_ENUM;
- static const Descriptor* GetMessageFieldDescriptor() {
- return NULL;
- }
-};
-
-template<typename T>
-struct RefTypeTraits<
- T, typename internal::enable_if<internal::is_same<string, T>::value>::type> {
- typedef RepeatedFieldRefIterator<T> iterator;
- typedef RepeatedFieldAccessor AccessorType;
- typedef string AccessorValueType;
- typedef string IteratorValueType;
- typedef string* IteratorPointerType;
- static const FieldDescriptor::CppType cpp_type =
- FieldDescriptor::CPPTYPE_STRING;
- static const Descriptor* GetMessageFieldDescriptor() {
- return NULL;
- }
-};
-
-template<typename T>
-struct MessageDescriptorGetter {
- static const Descriptor* get() {
- return T::default_instance().GetDescriptor();
- }
-};
-template<>
-struct MessageDescriptorGetter<Message> {
- static const Descriptor* get() {
- return NULL;
- }
-};
-
-template<typename T>
-struct RefTypeTraits<
- T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
- typedef RepeatedFieldRefIterator<T> iterator;
- typedef RepeatedFieldAccessor AccessorType;
- typedef Message AccessorValueType;
- typedef const T& IteratorValueType;
- typedef const T* IteratorPointerType;
- static const FieldDescriptor::CppType cpp_type =
- FieldDescriptor::CPPTYPE_MESSAGE;
- static const Descriptor* GetMessageFieldDescriptor() {
- return MessageDescriptorGetter<T>::get();
- }
-};
-} // namespace internal
-} // namespace protobuf
-} // namespace google
-#endif // GOOGLE_PROTOBUF_REPEATED_FIELD_REFLECTION_H__
diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc
index 4d8e77ce..5cc77bf3 100644
--- a/src/google/protobuf/source_context.pb.cc
+++ b/src/google/protobuf/source_context.pb.cc
@@ -29,6 +29,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
} // namespace
+void protobuf_AssignDesc_google_2fprotobuf_2fsource_5fcontext_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AssignDesc_google_2fprotobuf_2fsource_5fcontext_2eproto() {
protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
const ::google::protobuf::FileDescriptor* file =
@@ -60,6 +61,7 @@ inline void protobuf_AssignDescriptorsOnce() {
&protobuf_AssignDesc_google_2fprotobuf_2fsource_5fcontext_2eproto);
}
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
@@ -73,6 +75,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fsource_5fcontext_2eproto() {
delete SourceContext_reflection_;
}
+void protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto() {
static bool already_here = false;
if (already_here) return;
@@ -99,16 +102,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fsource_5fcontext_2eproto
}
} static_descriptor_initializer_google_2fprotobuf_2fsource_5fcontext_2eproto_;
-namespace {
-
-static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
-static void MergeFromFail(int line) {
- GOOGLE_CHECK(false) << __FILE__ << ":" << line;
-}
-
-} // namespace
-
-
// ===================================================================
#if !defined(_MSC_VER) || _MSC_VER >= 1900
@@ -281,7 +274,9 @@ int SourceContext::ByteSize() const {
void SourceContext::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceContext)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const SourceContext* source =
::google::protobuf::internal::DynamicCastToGenerated<const SourceContext>(
&from);
@@ -296,7 +291,9 @@ void SourceContext::MergeFrom(const ::google::protobuf::Message& from) {
void SourceContext::MergeFrom(const SourceContext& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceContext)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.file_name().size() > 0) {
file_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.file_name_);
diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc
index dd6b78d1..a551384c 100644
--- a/src/google/protobuf/struct.pb.cc
+++ b/src/google/protobuf/struct.pb.cc
@@ -45,6 +45,7 @@ const ::google::protobuf::EnumDescriptor* NullValue_descriptor_ = NULL;
} // namespace
+void protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto() {
protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
const ::google::protobuf::FileDescriptor* file =
@@ -116,6 +117,7 @@ inline void protobuf_AssignDescriptorsOnce() {
&protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto);
}
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
@@ -147,6 +149,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fstruct_2eproto() {
delete ListValue_reflection_;
}
+void protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto() {
static bool already_here = false;
if (already_here) return;
@@ -203,16 +206,6 @@ bool NullValue_IsValid(int value) {
}
-namespace {
-
-static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
-static void MergeFromFail(int line) {
- GOOGLE_CHECK(false) << __FILE__ << ":" << line;
-}
-
-} // namespace
-
-
// ===================================================================
#if !defined(_MSC_VER) || _MSC_VER >= 1900
@@ -348,18 +341,51 @@ void Struct::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
// @@protoc_insertion_point(serialize_start:google.protobuf.Struct)
// map<string, .google.protobuf.Value> fields = 1;
- {
- ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
- for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
- it = this->fields().begin();
- it != this->fields().end(); ++it) {
- entry.reset(fields_.NewEntryWrapper(it->first, it->second));
- ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
- 1, *entry, output);
- ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
- it->first.data(), it->first.length(),
- ::google::protobuf::internal::WireFormatLite::SERIALIZE,
- "google.protobuf.Struct.FieldsEntry.key");
+ if (!this->fields().empty()) {
+ typedef ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_pointer
+ ConstPtr;
+ typedef ConstPtr SortItem;
+ typedef ::google::protobuf::internal::CompareByDerefFirst<SortItem> Less;
+ struct Utf8Check {
+ static void Check(ConstPtr p) {
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+ p->first.data(), p->first.length(),
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+ "google.protobuf.Struct.FieldsEntry.key");
+ }
+ };
+
+ if (output->IsSerializationDeterminstic() &&
+ this->fields().size() > 1) {
+ ::google::protobuf::scoped_array<SortItem> items(
+ new SortItem[this->fields().size()]);
+ typedef ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::size_type size_type;
+ size_type n = 0;
+ for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
+ it = this->fields().begin();
+ it != this->fields().end(); ++it, ++n) {
+ items[n] = SortItem(&*it);
+ }
+ ::std::sort(&items[0], &items[n], Less());
+ ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
+ for (size_type i = 0; i < n; i++) {
+ entry.reset(fields_.NewEntryWrapper(
+ items[i]->first, items[i]->second));
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 1, *entry, output);
+ Utf8Check::Check(items[i]);
+ }
+ } else {
+ ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
+ for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
+ it = this->fields().begin();
+ it != this->fields().end(); ++it) {
+ entry.reset(fields_.NewEntryWrapper(
+ it->first, it->second));
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 1, *entry, output);
+ Utf8Check::Check(&*it);
+ }
}
}
@@ -370,19 +396,55 @@ void Struct::SerializeWithCachedSizes(
bool deterministic, ::google::protobuf::uint8* target) const {
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Struct)
// map<string, .google.protobuf.Value> fields = 1;
- {
- ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
- for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
- it = this->fields().begin();
- it != this->fields().end(); ++it) {
- entry.reset(fields_.NewEntryWrapper(it->first, it->second));
- target = ::google::protobuf::internal::WireFormatLite::
- InternalWriteMessageNoVirtualToArray(
- 1, *entry, false, target);
- ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
- it->first.data(), it->first.length(),
- ::google::protobuf::internal::WireFormatLite::SERIALIZE,
- "google.protobuf.Struct.FieldsEntry.key");
+ if (!this->fields().empty()) {
+ typedef ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_pointer
+ ConstPtr;
+ typedef ConstPtr SortItem;
+ typedef ::google::protobuf::internal::CompareByDerefFirst<SortItem> Less;
+ struct Utf8Check {
+ static void Check(ConstPtr p) {
+ ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+ p->first.data(), p->first.length(),
+ ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+ "google.protobuf.Struct.FieldsEntry.key");
+ }
+ };
+
+ if (deterministic &&
+ this->fields().size() > 1) {
+ ::google::protobuf::scoped_array<SortItem> items(
+ new SortItem[this->fields().size()]);
+ typedef ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::size_type size_type;
+ size_type n = 0;
+ for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
+ it = this->fields().begin();
+ it != this->fields().end(); ++it, ++n) {
+ items[n] = SortItem(&*it);
+ }
+ ::std::sort(&items[0], &items[n], Less());
+ ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
+ for (size_type i = 0; i < n; i++) {
+ entry.reset(fields_.NewEntryWrapper(
+ items[i]->first, items[i]->second));
+ target = ::google::protobuf::internal::WireFormatLite::
+ InternalWriteMessageNoVirtualToArray(
+ 1, *entry, deterministic, target);
+;
+ Utf8Check::Check(items[i]);
+ }
+ } else {
+ ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
+ for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
+ it = this->fields().begin();
+ it != this->fields().end(); ++it) {
+ entry.reset(fields_.NewEntryWrapper(
+ it->first, it->second));
+ target = ::google::protobuf::internal::WireFormatLite::
+ InternalWriteMessageNoVirtualToArray(
+ 1, *entry, deterministic, target);
+;
+ Utf8Check::Check(&*it);
+ }
}
}
@@ -415,7 +477,9 @@ int Struct::ByteSize() const {
void Struct::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Struct)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const Struct* source =
::google::protobuf::internal::DynamicCastToGenerated<const Struct>(
&from);
@@ -430,7 +494,9 @@ void Struct::MergeFrom(const ::google::protobuf::Message& from) {
void Struct::MergeFrom(const Struct& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Struct)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
fields_.MergeFrom(from.fields_);
}
@@ -881,7 +947,9 @@ int Value::ByteSize() const {
void Value::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Value)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const Value* source =
::google::protobuf::internal::DynamicCastToGenerated<const Value>(
&from);
@@ -896,7 +964,9 @@ void Value::MergeFrom(const ::google::protobuf::Message& from) {
void Value::MergeFrom(const Value& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Value)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
switch (from.kind_case()) {
case kNullValue: {
set_null_value(from.null_value());
@@ -1406,7 +1476,9 @@ int ListValue::ByteSize() const {
void ListValue::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ListValue)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const ListValue* source =
::google::protobuf::internal::DynamicCastToGenerated<const ListValue>(
&from);
@@ -1421,7 +1493,9 @@ void ListValue::MergeFrom(const ::google::protobuf::Message& from) {
void ListValue::MergeFrom(const ListValue& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ListValue)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
values_.MergeFrom(from.values_);
}
diff --git a/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h b/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h
index a0116a60..7314ee4f 100644
--- a/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h
+++ b/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h
@@ -128,6 +128,24 @@ inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
return old_value;
}
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ return __atomic_add_fetch(ptr, increment, __ATOMIC_RELAXED);
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+ __atomic_store_n(ptr, value, __ATOMIC_RELAXED);
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+ Atomic64 new_value) {
+ return __atomic_exchange_n(ptr, new_value, __ATOMIC_RELAXED);
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+ return __atomic_load_n(ptr, __ATOMIC_RELAXED);
+}
+
#endif // defined(__LP64__)
} // namespace internal
diff --git a/src/google/protobuf/stubs/callback.h b/src/google/protobuf/stubs/callback.h
index 87271c5e..bbd507a8 100644
--- a/src/google/protobuf/stubs/callback.h
+++ b/src/google/protobuf/stubs/callback.h
@@ -381,6 +381,8 @@ class MethodResultCallback_5_2 : public ResultCallback2<R, A1, A2> {
typename remove_reference<P5>::type p5_;
};
+} // namespace internal
+
// See Closure.
inline Closure* NewCallback(void (*function)()) {
return new internal::FunctionClosure0(function, true);
@@ -533,8 +535,6 @@ inline ResultCallback2<R, A1, A2>* NewPermanentCallback(
p2, p3, p4, p5);
}
-} // namespace internal
-
// A function which does nothing. Useful for creating no-op callbacks, e.g.:
// Closure* nothing = NewCallback(&DoNothing);
void LIBPROTOBUF_EXPORT DoNothing();
diff --git a/src/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc
index 25bae9b0..f9e2cfd4 100644
--- a/src/google/protobuf/stubs/common_unittest.cc
+++ b/src/google/protobuf/stubs/common_unittest.cc
@@ -41,8 +41,6 @@
namespace google {
namespace protobuf {
-using internal::NewCallback;
-using internal::NewPermanentCallback;
namespace {
// TODO(kenton): More tests.
diff --git a/src/google/protobuf/stubs/int128.cc b/src/google/protobuf/stubs/int128.cc
index 3a36b4b1..a5090801 100644
--- a/src/google/protobuf/stubs/int128.cc
+++ b/src/google/protobuf/stubs/int128.cc
@@ -145,15 +145,15 @@ std::ostream& operator<<(std::ostream& o, const uint128& b) {
std::streamsize div_base_log;
switch (flags & std::ios::basefield) {
case std::ios::hex:
- div = GOOGLE_ULONGLONG(0x1000000000000000); // 16^15
+ div = static_cast<uint64>(GOOGLE_ULONGLONG(0x1000000000000000)); // 16^15
div_base_log = 15;
break;
case std::ios::oct:
- div = GOOGLE_ULONGLONG(01000000000000000000000); // 8^21
+ div = static_cast<uint64>(GOOGLE_ULONGLONG(01000000000000000000000)); // 8^21
div_base_log = 21;
break;
default: // std::ios::dec
- div = GOOGLE_ULONGLONG(10000000000000000000); // 10^19
+ div = static_cast<uint64>(GOOGLE_ULONGLONG(10000000000000000000)); // 10^19
div_base_log = 19;
break;
}
diff --git a/src/google/protobuf/stubs/map_util.h b/src/google/protobuf/stubs/map_util.h
index 4cccbbed..887f12a6 100644
--- a/src/google/protobuf/stubs/map_util.h
+++ b/src/google/protobuf/stubs/map_util.h
@@ -208,7 +208,7 @@ typename Collection::value_type::second_type::element_type&
FindLinkedPtrOrDie(const Collection& collection,
const typename Collection::value_type::first_type& key) {
typename Collection::const_iterator it = collection.find(key);
- CHECK(it != collection.end()) << "key not found: " << key;
+ GOOGLE_CHECK(it != collection.end()) << "key not found: " << key;
// Since linked_ptr::operator*() is a const member returning a non const,
// we do not need a version of this function taking a non const collection.
return *it->second;
@@ -337,14 +337,15 @@ bool InsertIfNotPresent(
template <class Collection>
void InsertOrDie(Collection* const collection,
const typename Collection::value_type& value) {
- CHECK(InsertIfNotPresent(collection, value)) << "duplicate value: " << value;
+ GOOGLE_CHECK(InsertIfNotPresent(collection, value))
+ << "duplicate value: " << value;
}
// Same as above except doesn't log the value on error.
template <class Collection>
void InsertOrDieNoPrint(Collection* const collection,
const typename Collection::value_type& value) {
- CHECK(InsertIfNotPresent(collection, value)) << "duplicate value.";
+ GOOGLE_CHECK(InsertIfNotPresent(collection, value)) << "duplicate value.";
}
// Inserts the key-value pair into the collection. Dies if key was already
diff --git a/src/google/protobuf/stubs/once_unittest.cc b/src/google/protobuf/stubs/once_unittest.cc
index 37def58d..d5f7779e 100644
--- a/src/google/protobuf/stubs/once_unittest.cc
+++ b/src/google/protobuf/stubs/once_unittest.cc
@@ -43,7 +43,6 @@
namespace google {
namespace protobuf {
-using internal::NewCallback;
namespace {
class OnceInitTest : public testing::Test {
@@ -128,11 +127,11 @@ class OnceInitTest : public testing::Test {
};
TestThread* RunInitOnceInNewThread() {
- return new TestThread(internal::NewCallback(this, &OnceInitTest::InitOnce));
+ return new TestThread(NewCallback(this, &OnceInitTest::InitOnce));
}
TestThread* RunInitRecursiveOnceInNewThread() {
return new TestThread(
- internal::NewCallback(this, &OnceInitTest::InitRecursiveOnce));
+ NewCallback(this, &OnceInitTest::InitRecursiveOnce));
}
enum State {
diff --git a/src/google/protobuf/stubs/port.h b/src/google/protobuf/stubs/port.h
index 328258b7..d7f93b4c 100644
--- a/src/google/protobuf/stubs/port.h
+++ b/src/google/protobuf/stubs/port.h
@@ -109,15 +109,15 @@ typedef unsigned __int16 uint16;
typedef unsigned __int32 uint32;
typedef unsigned __int64 uint64;
#else
-typedef signed char int8;
-typedef short int16;
-typedef int int32;
-typedef long long int64;
-
-typedef unsigned char uint8;
-typedef unsigned short uint16;
-typedef unsigned int uint32;
-typedef unsigned long long uint64;
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef int64_t int64;
+
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
#endif
// long long macros to be used because gcc and vc++ use different suffixes,
@@ -131,8 +131,10 @@ typedef unsigned long long uint64;
#define GOOGLE_ULONGLONG(x) x##UI64
#define GOOGLE_LL_FORMAT "I64" // As in printf("%I64d", ...)
#else
+// By long long, we actually mean int64.
#define GOOGLE_LONGLONG(x) x##LL
#define GOOGLE_ULONGLONG(x) x##ULL
+// Used to format real long long integers.
#define GOOGLE_LL_FORMAT "ll" // As in "%lld". Note that "q" is poor form also.
#endif
diff --git a/src/google/protobuf/testdata/golden_message_maps b/src/google/protobuf/testdata/golden_message_maps
new file mode 100644
index 00000000..c70a4d7c
--- /dev/null
+++ b/src/google/protobuf/testdata/golden_message_maps
Binary files differ
diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc
index 3d07b127..470512ed 100644
--- a/src/google/protobuf/testing/file.cc
+++ b/src/google/protobuf/testing/file.cc
@@ -91,6 +91,7 @@ bool File::WriteStringToFile(const string& contents, const string& name) {
if (fwrite(contents.data(), 1, contents.size(), file) != contents.size()) {
GOOGLE_LOG(ERROR) << "fwrite(" << name << "): " << strerror(errno);
+ fclose(file);
return false;
}
@@ -140,12 +141,12 @@ void File::DeleteRecursively(const string& name,
#ifdef _MSC_VER
// This interface is so weird.
- WIN32_FIND_DATA find_data;
- HANDLE find_handle = FindFirstFile((name + "/*").c_str(), &find_data);
+ WIN32_FIND_DATAA find_data;
+ HANDLE find_handle = FindFirstFileA((name + "/*").c_str(), &find_data);
if (find_handle == INVALID_HANDLE_VALUE) {
// Just delete it, whatever it is.
- DeleteFile(name.c_str());
- RemoveDirectory(name.c_str());
+ DeleteFileA(name.c_str());
+ RemoveDirectoryA(name.c_str());
return;
}
@@ -155,15 +156,15 @@ void File::DeleteRecursively(const string& name,
string path = name + "/" + entry_name;
if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
DeleteRecursively(path, NULL, NULL);
- RemoveDirectory(path.c_str());
+ RemoveDirectoryA(path.c_str());
} else {
- DeleteFile(path.c_str());
+ DeleteFileA(path.c_str());
}
}
- } while(FindNextFile(find_handle, &find_data));
+ } while(FindNextFileA(find_handle, &find_data));
FindClose(find_handle);
- RemoveDirectory(name.c_str());
+ RemoveDirectoryA(name.c_str());
#else
// Use opendir()! Yay!
// lstat = Don't follow symbolic links.
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index d49d8588..66b2648b 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -759,6 +759,20 @@ class TextFormat::Parser::ParserImpl {
}
return true;
}
+ if (TryConsume("[")) {
+ while (true) {
+ if (!LookingAt("{") && !LookingAt("<")) {
+ DO(SkipFieldValue());
+ } else {
+ DO(SkipFieldMessage());
+ }
+ if (TryConsume("]")) {
+ break;
+ }
+ DO(Consume(","));
+ }
+ return true;
+ }
// Possible field values other than string:
// 12345 => TYPE_INTEGER
// -12345 => TYPE_SYMBOL + TYPE_INTEGER
diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc
index 2ec4bc56..487e62b0 100644
--- a/src/google/protobuf/timestamp.pb.cc
+++ b/src/google/protobuf/timestamp.pb.cc
@@ -29,6 +29,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
} // namespace
+void protobuf_AssignDesc_google_2fprotobuf_2ftimestamp_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AssignDesc_google_2fprotobuf_2ftimestamp_2eproto() {
protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto();
const ::google::protobuf::FileDescriptor* file =
@@ -61,6 +62,7 @@ inline void protobuf_AssignDescriptorsOnce() {
&protobuf_AssignDesc_google_2fprotobuf_2ftimestamp_2eproto);
}
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
@@ -74,6 +76,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2ftimestamp_2eproto() {
delete Timestamp_reflection_;
}
+void protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto() {
static bool already_here = false;
if (already_here) return;
@@ -101,16 +104,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2ftimestamp_2eproto {
}
} static_descriptor_initializer_google_2fprotobuf_2ftimestamp_2eproto_;
-namespace {
-
-static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
-static void MergeFromFail(int line) {
- GOOGLE_CHECK(false) << __FILE__ << ":" << line;
-}
-
-} // namespace
-
-
// ===================================================================
#if !defined(_MSC_VER) || _MSC_VER >= 1900
@@ -206,7 +199,7 @@ void Timestamp::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -336,7 +329,9 @@ int Timestamp::ByteSize() const {
void Timestamp::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Timestamp)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const Timestamp* source =
::google::protobuf::internal::DynamicCastToGenerated<const Timestamp>(
&from);
@@ -351,7 +346,9 @@ void Timestamp::MergeFrom(const ::google::protobuf::Message& from) {
void Timestamp::MergeFrom(const Timestamp& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Timestamp)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.seconds() != 0) {
set_seconds(from.seconds());
}
diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc
index f9182a75..a2a7f282 100644
--- a/src/google/protobuf/type.pb.cc
+++ b/src/google/protobuf/type.pb.cc
@@ -44,6 +44,7 @@ const ::google::protobuf::EnumDescriptor* Syntax_descriptor_ = NULL;
} // namespace
+void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto() {
protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
const ::google::protobuf::FileDescriptor* file =
@@ -159,6 +160,7 @@ inline void protobuf_AssignDescriptorsOnce() {
&protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto);
}
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
@@ -188,6 +190,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto() {
delete Option_reflection_;
}
+void protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto() {
static bool already_here = false;
if (already_here) return;
@@ -272,16 +275,6 @@ bool Syntax_IsValid(int value) {
}
-namespace {
-
-static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
-static void MergeFromFail(int line) {
- GOOGLE_CHECK(false) << __FILE__ << ":" << line;
-}
-
-} // namespace
-
-
// ===================================================================
#if !defined(_MSC_VER) || _MSC_VER >= 1900
@@ -658,7 +651,9 @@ int Type::ByteSize() const {
void Type::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Type)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const Type* source =
::google::protobuf::internal::DynamicCastToGenerated<const Type>(
&from);
@@ -673,7 +668,9 @@ void Type::MergeFrom(const ::google::protobuf::Message& from) {
void Type::MergeFrom(const Type& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Type)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
fields_.MergeFrom(from.fields_);
oneofs_.MergeFrom(from.oneofs_);
options_.MergeFrom(from.options_);
@@ -1128,7 +1125,7 @@ void Field::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -1581,7 +1578,9 @@ int Field::ByteSize() const {
void Field::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Field)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const Field* source =
::google::protobuf::internal::DynamicCastToGenerated<const Field>(
&from);
@@ -1596,7 +1595,9 @@ void Field::MergeFrom(const ::google::protobuf::Message& from) {
void Field::MergeFrom(const Field& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Field)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
options_.MergeFrom(from.options_);
if (from.kind() != 0) {
set_kind(from.kind());
@@ -2285,7 +2286,9 @@ int Enum::ByteSize() const {
void Enum::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Enum)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const Enum* source =
::google::protobuf::internal::DynamicCastToGenerated<const Enum>(
&from);
@@ -2300,7 +2303,9 @@ void Enum::MergeFrom(const ::google::protobuf::Message& from) {
void Enum::MergeFrom(const Enum& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Enum)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
enumvalue_.MergeFrom(from.enumvalue_);
options_.MergeFrom(from.options_);
if (from.name().size() > 0) {
@@ -2764,7 +2769,9 @@ int EnumValue::ByteSize() const {
void EnumValue::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValue)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const EnumValue* source =
::google::protobuf::internal::DynamicCastToGenerated<const EnumValue>(
&from);
@@ -2779,7 +2786,9 @@ void EnumValue::MergeFrom(const ::google::protobuf::Message& from) {
void EnumValue::MergeFrom(const EnumValue& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValue)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
options_.MergeFrom(from.options_);
if (from.name().size() > 0) {
@@ -3133,7 +3142,9 @@ int Option::ByteSize() const {
void Option::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Option)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const Option* source =
::google::protobuf::internal::DynamicCastToGenerated<const Option>(
&from);
@@ -3148,7 +3159,9 @@ void Option::MergeFrom(const ::google::protobuf::Message& from) {
void Option::MergeFrom(const Option& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Option)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.name().size() > 0) {
name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
index d4e383da..8ee99d48 100644
--- a/src/google/protobuf/unknown_field_set.cc
+++ b/src/google/protobuf/unknown_field_set.cc
@@ -69,28 +69,14 @@ const UnknownFieldSet* UnknownFieldSet::default_instance() {
return default_unknown_field_set_instance_;
}
-UnknownFieldSet::UnknownFieldSet()
- : fields_(NULL) {}
-
-UnknownFieldSet::~UnknownFieldSet() {
- Clear();
- delete fields_;
-}
-
void UnknownFieldSet::ClearFallback() {
- if (fields_ != NULL) {
- for (int i = 0; i < fields_->size(); i++) {
- (*fields_)[i].Delete();
- }
- delete fields_;
- fields_ = NULL;
- }
-}
-
-void UnknownFieldSet::ClearAndFreeMemory() {
- if (fields_ != NULL) {
- Clear();
- }
+ GOOGLE_DCHECK(fields_ != NULL && fields_->size() > 0);
+ int n = fields_->size();
+ do {
+ (*fields_)[--n].Delete();
+ } while (n > 0);
+ delete fields_;
+ fields_ = NULL;
}
void UnknownFieldSet::InternalMergeFrom(const UnknownFieldSet& other) {
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index 612a942a..aa752916 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -241,8 +241,14 @@ class LIBPROTOBUF_EXPORT UnknownField {
// ===================================================================
// inline implementations
+inline UnknownFieldSet::UnknownFieldSet() : fields_(NULL) {}
+
+inline UnknownFieldSet::~UnknownFieldSet() { Clear(); }
+
+inline void UnknownFieldSet::ClearAndFreeMemory() { Clear(); }
+
inline void UnknownFieldSet::Clear() {
- if (fields_) {
+ if (fields_ != NULL) {
ClearFallback();
}
}
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc
index 21d7a2e4..fa31f763 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.cc
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc
@@ -64,6 +64,7 @@ DefaultValueObjectWriter::DefaultValueObjectWriter(
type_(type),
current_(NULL),
root_(NULL),
+ suppress_empty_list_(false),
field_scrub_callback_(NULL),
ow_(ow) {}
@@ -164,7 +165,10 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes(
if (current_ == NULL) {
ow_->RenderBytes(name, value);
} else {
- RenderDataPiece(name, DataPiece(value, false, true));
+ // Since StringPiece is essentially a pointer, takes a copy of "value" to
+ // avoid ownership issues.
+ string_values_.push_back(new string(value.ToString()));
+ RenderDataPiece(name, DataPiece(*string_values_.back(), false, true));
}
return this;
}
@@ -184,12 +188,10 @@ void DefaultValueObjectWriter::RegisterFieldScrubCallBack(
field_scrub_callback_.reset(field_scrub_callback.release());
}
-DefaultValueObjectWriter::Node::Node(const string& name,
- const google::protobuf::Type* type,
- NodeKind kind, const DataPiece& data,
- bool is_placeholder,
- const vector<string>& path,
- FieldScrubCallBack* field_scrub_callback)
+DefaultValueObjectWriter::Node::Node(
+ const string& name, const google::protobuf::Type* type, NodeKind kind,
+ const DataPiece& data, bool is_placeholder, const vector<string>& path,
+ bool suppress_empty_list, FieldScrubCallBack* field_scrub_callback)
: name_(name),
type_(type),
kind_(kind),
@@ -197,6 +199,7 @@ DefaultValueObjectWriter::Node::Node(const string& name,
data_(data),
is_placeholder_(is_placeholder),
path_(path),
+ suppress_empty_list_(suppress_empty_list),
field_scrub_callback_(field_scrub_callback) {}
DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild(
@@ -230,6 +233,9 @@ void DefaultValueObjectWriter::Node::WriteTo(ObjectWriter* ow) {
// Write out lists. If we didn't have any list in response, write out empty
// list.
if (kind_ == LIST) {
+ // Suppress empty lists if requested.
+ if (suppress_empty_list_ && is_placeholder_) return;
+
ow->StartList(name_);
WriteChildren(ow);
ow->EndList();
@@ -366,7 +372,7 @@ void DefaultValueObjectWriter::Node::PopulateChildren(
field.json_name(), field_type, kind,
kind == PRIMITIVE ? CreateDefaultDataPieceForField(field, typeinfo)
: DataPiece::NullData(),
- true, path, field_scrub_callback_));
+ true, path, suppress_empty_list_, field_scrub_callback_));
new_children.push_back(child.release());
}
// Adds all leftover nodes in children_ to the beginning of new_child.
@@ -462,7 +468,8 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
if (current_ == NULL) {
vector<string> path;
root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(),
- false, path, field_scrub_callback_.get()));
+ false, path, suppress_empty_list_,
+ field_scrub_callback_.get()));
root_->PopulateChildren(typeinfo_);
current_ = root_.get();
return this;
@@ -478,7 +485,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
: NULL),
OBJECT, DataPiece::NullData(), false,
child == NULL ? current_->path() : child->path(),
- field_scrub_callback_.get()));
+ suppress_empty_list_, field_scrub_callback_.get()));
child = node.get();
current_->AddChild(node.release());
}
@@ -509,7 +516,8 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartList(
if (current_ == NULL) {
vector<string> path;
root_.reset(new Node(name.ToString(), &type_, LIST, DataPiece::NullData(),
- false, path, field_scrub_callback_.get()));
+ false, path, suppress_empty_list_,
+ field_scrub_callback_.get()));
current_ = root_.get();
return this;
}
@@ -519,7 +527,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartList(
google::protobuf::scoped_ptr<Node> node(
new Node(name.ToString(), NULL, LIST, DataPiece::NullData(), false,
child == NULL ? current_->path() : child->path(),
- field_scrub_callback_.get()));
+ suppress_empty_list_, field_scrub_callback_.get()));
child = node.get();
current_->AddChild(node.release());
}
@@ -577,7 +585,7 @@ void DefaultValueObjectWriter::RenderDataPiece(StringPiece name,
google::protobuf::scoped_ptr<Node> node(
new Node(name.ToString(), NULL, PRIMITIVE, data, false,
child == NULL ? current_->path() : child->path(),
- field_scrub_callback_.get()));
+ suppress_empty_list_, field_scrub_callback_.get()));
child = node.get();
current_->AddChild(node.release());
} else {
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h
index 1d85bed8..5f3b25f3 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.h
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.h
@@ -122,6 +122,10 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// field_scrub_callback pointer is also transferred to this class
void RegisterFieldScrubCallBack(FieldScrubCallBackPtr field_scrub_callback);
+ // If set to true, empty lists are suppressed from output when default values
+ // are written.
+ void set_suppress_empty_list(bool value) { suppress_empty_list_ = value; }
+
private:
enum NodeKind {
PRIMITIVE = 0,
@@ -136,7 +140,7 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
public:
Node(const string& name, const google::protobuf::Type* type, NodeKind kind,
const DataPiece& data, bool is_placeholder, const vector<string>& path,
- FieldScrubCallBack* field_scrub_callback);
+ bool suppress_empty_list, FieldScrubCallBack* field_scrub_callback);
virtual ~Node() {
for (int i = 0; i < children_.size(); ++i) {
delete children_[i];
@@ -212,6 +216,9 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// Path of the field of this node
std::vector<string> path_;
+ // Whether to suppress empty list output.
+ bool suppress_empty_list_;
+
// Pointer to function for determining whether a field needs to be scrubbed
// or not. This callback is owned by the creator of this node.
FieldScrubCallBack* field_scrub_callback_;
@@ -257,6 +264,9 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// The stack to hold the path of Nodes from current_ to root_;
std::stack<Node*> stack_;
+ // Whether to suppress output of empty lists.
+ bool suppress_empty_list_;
+
// Unique Pointer to function for determining whether a field needs to be
// scrubbed or not.
FieldScrubCallBackPtr field_scrub_callback_;
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 8254c0fa..e1dd697a 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
@@ -149,6 +149,39 @@ TEST_P(DefaultValueObjectWriterTest, ShouldRetainUnknownField) {
}
+class DefaultValueObjectWriterSuppressListTest
+ : public BaseDefaultValueObjectWriterTest {
+ protected:
+ DefaultValueObjectWriterSuppressListTest()
+ : BaseDefaultValueObjectWriterTest(DefaultValueTest::descriptor()) {
+ testing_->set_suppress_empty_list(true);
+ }
+ ~DefaultValueObjectWriterSuppressListTest() {}
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+ DefaultValueObjectWriterSuppressListTest,
+ ::testing::Values(
+ testing::USE_TYPE_RESOLVER));
+
+TEST_P(DefaultValueObjectWriterSuppressListTest, Empty) {
+ // Set expectation. Emtpy lists should be suppressed.
+ expects_.StartObject("")
+ ->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", "")
+ ->RenderString("enumValue", "ENUM_FIRST")
+ ->EndObject();
+
+ // Actual testing
+ testing_->StartObject("")->EndObject();
+}
} // namespace testing
} // namespace converter
} // namespace util
diff --git a/src/google/protobuf/util/internal/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc
index 7a1a6cbd..0c38aeb9 100644
--- a/src/google/protobuf/util/internal/proto_writer.cc
+++ b/src/google/protobuf/util/internal/proto_writer.cc
@@ -298,7 +298,9 @@ ProtoWriter::ProtoElement::ProtoElement(const TypeInfo* typeinfo,
proto3_(type.syntax() == google::protobuf::SYNTAX_PROTO3),
type_(type),
size_index_(-1),
- array_index_(-1) {
+ array_index_(-1),
+ // oneof_indices_ values are 1-indexed (0 means not present).
+ oneof_indices_(type.oneofs_size() + 1) {
if (!proto3_) {
required_fields_ = GetRequiredFields(type_);
}
@@ -312,13 +314,15 @@ ProtoWriter::ProtoElement::ProtoElement(ProtoWriter::ProtoElement* parent,
ow_(this->parent()->ow_),
parent_field_(field),
typeinfo_(this->parent()->typeinfo_),
- proto3_(this->parent()->proto3_),
+ proto3_(type.syntax() == google::protobuf::SYNTAX_PROTO3),
type_(type),
size_index_(
!is_list && field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE
? ow_->size_insert_.size()
: -1),
- array_index_(is_list ? 0 : -1) {
+ array_index_(is_list ? 0 : -1),
+ // oneof_indices_ values are 1-indexed (0 means not present).
+ oneof_indices_(type_.oneofs_size() + 1) {
if (!is_list) {
if (ow_->IsRepeated(*field)) {
// Update array_index_ if it is an explicit list.
@@ -411,11 +415,11 @@ string ProtoWriter::ProtoElement::ToString() const {
}
bool ProtoWriter::ProtoElement::IsOneofIndexTaken(int32 index) {
- return ContainsKey(oneof_indices_, index);
+ return oneof_indices_[index];
}
void ProtoWriter::ProtoElement::TakeOneofIndex(int32 index) {
- InsertIfNotPresent(&oneof_indices_, index);
+ oneof_indices_[index] = true;
}
void ProtoWriter::InvalidName(StringPiece unknown_name, StringPiece message) {
@@ -573,10 +577,19 @@ ProtoWriter* ProtoWriter::RenderPrimitiveField(
// Pushing a ProtoElement and then pop it off at the end for 2 purposes:
// error location reporting and required field accounting.
- element_.reset(new ProtoElement(element_.release(), &field, type, false));
+ //
+ // For proto3, since there is no required field tracking, we only need to push
+ // ProtoElement for error cases.
+ if (!element_->proto3()) {
+ element_.reset(new ProtoElement(element_.release(), &field, type, false));
+ }
if (field.kind() == google::protobuf::Field_Kind_TYPE_UNKNOWN ||
field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) {
+ // Push a ProtoElement for location reporting purposes.
+ if (element_->proto3()) {
+ element_.reset(new ProtoElement(element_.release(), &field, type, false));
+ }
InvalidValue(field.type_url().empty()
? google::protobuf::Field_Kind_Name(field.kind())
: field.type_url(),
@@ -657,11 +670,18 @@ ProtoWriter* ProtoWriter::RenderPrimitiveField(
}
if (!status.ok()) {
+ // Push a ProtoElement for location reporting purposes.
+ if (element_->proto3()) {
+ element_.reset(new ProtoElement(element_.release(), &field, type, false));
+ }
InvalidValue(google::protobuf::Field_Kind_Name(field.kind()),
status.error_message());
+ element_.reset(element()->pop());
+ return this;
}
- element_.reset(element()->pop());
+ if (!element_->proto3()) element_.reset(element()->pop());
+
return this;
}
diff --git a/src/google/protobuf/util/internal/proto_writer.h b/src/google/protobuf/util/internal/proto_writer.h
index 8b7c6c34..7f1108ab 100644
--- a/src/google/protobuf/util/internal/proto_writer.h
+++ b/src/google/protobuf/util/internal/proto_writer.h
@@ -32,8 +32,8 @@
#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTO_WRITER_H__
#include <deque>
-#include <google/protobuf/stubs/hash.h>
#include <string>
+#include <vector>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
@@ -45,6 +45,7 @@
#include <google/protobuf/util/internal/structured_objectwriter.h>
#include <google/protobuf/util/type_resolver.h>
#include <google/protobuf/stubs/bytestream.h>
+#include <google/protobuf/stubs/hash.h>
namespace google {
namespace protobuf {
@@ -191,6 +192,8 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter {
// generate an error.
void TakeOneofIndex(int32 index);
+ bool proto3() { return proto3_; }
+
private:
// Used for access to variables of the enclosing instance of
// ProtoWriter.
@@ -203,7 +206,7 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter {
// TypeInfo to lookup types.
const TypeInfo* typeinfo_;
- // Whether the root type is a proto3 or not.
+ // Whether the type_ is proto3 or not.
bool proto3_;
// Additional variables if this element is a message:
@@ -221,7 +224,7 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter {
// 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_;
+ std::vector<bool> oneof_indices_;
GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoElement);
};
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
index 1825f556..73e05cfe 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -907,7 +907,7 @@ Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow,
// conversions as much as possible. Because ToSnakeCase sometimes returns the
// wrong value.
google::protobuf::scoped_ptr<ResultCallback1<util::Status, StringPiece> > callback(
- ::google::protobuf::internal::NewPermanentCallback(&RenderOneFieldPath, ow));
+ NewPermanentCallback(&RenderOneFieldPath, ow));
return DecodeCompactFieldMaskPaths(data.str(), callback.get());
}
diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc
index 6d45a4f9..d7ac2dba 100644
--- a/src/google/protobuf/util/json_util.cc
+++ b/src/google/protobuf/util/json_util.cc
@@ -177,6 +177,66 @@ util::Status JsonToBinaryString(TypeResolver* resolver,
resolver, type_url, &input_stream, &output_stream, options);
}
+namespace {
+const char* kTypeUrlPrefix = "type.googleapis.com";
+TypeResolver* generated_type_resolver_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(generated_type_resolver_init_);
+
+string GetTypeUrl(const Message& message) {
+ return string(kTypeUrlPrefix) + "/" + message.GetDescriptor()->full_name();
+}
+
+void DeleteGeneratedTypeResolver() { delete generated_type_resolver_; }
+
+void InitGeneratedTypeResolver() {
+ generated_type_resolver_ = NewTypeResolverForDescriptorPool(
+ kTypeUrlPrefix, DescriptorPool::generated_pool());
+ ::google::protobuf::internal::OnShutdown(&DeleteGeneratedTypeResolver);
+}
+
+TypeResolver* GetGeneratedTypeResolver() {
+ ::google::protobuf::GoogleOnceInit(&generated_type_resolver_init_, &InitGeneratedTypeResolver);
+ return generated_type_resolver_;
+}
+} // namespace
+
+util::Status MessageToJsonString(const Message& message, string* output,
+ const JsonOptions& options) {
+ const DescriptorPool* pool = message.GetDescriptor()->file()->pool();
+ TypeResolver* resolver =
+ pool == DescriptorPool::generated_pool()
+ ? GetGeneratedTypeResolver()
+ : NewTypeResolverForDescriptorPool(kTypeUrlPrefix, pool);
+ util::Status result =
+ BinaryToJsonString(resolver, GetTypeUrl(message),
+ message.SerializeAsString(), output, options);
+ if (pool != DescriptorPool::generated_pool()) {
+ delete resolver;
+ }
+ return result;
+}
+
+util::Status JsonStringToMessage(const string& input, Message* message,
+ const JsonParseOptions& options) {
+ const DescriptorPool* pool = message->GetDescriptor()->file()->pool();
+ TypeResolver* resolver =
+ pool == DescriptorPool::generated_pool()
+ ? GetGeneratedTypeResolver()
+ : NewTypeResolverForDescriptorPool(kTypeUrlPrefix, pool);
+ string binary;
+ util::Status result = JsonToBinaryString(
+ resolver, GetTypeUrl(*message), input, &binary, options);
+ if (result.ok() && !message->ParseFromString(binary)) {
+ result =
+ util::Status(util::error::INVALID_ARGUMENT,
+ "JSON transcoder produced invalid protobuf output.");
+ }
+ if (pool != DescriptorPool::generated_pool()) {
+ delete resolver;
+ }
+ return result;
+}
+
} // namespace util
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/util/json_util.h b/src/google/protobuf/util/json_util.h
index b4c2579b..6d3cee52 100644
--- a/src/google/protobuf/util/json_util.h
+++ b/src/google/protobuf/util/json_util.h
@@ -33,6 +33,7 @@
#ifndef GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__
#define GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__
+#include <google/protobuf/message.h>
#include <google/protobuf/util/type_resolver.h>
#include <google/protobuf/stubs/bytestream.h>
@@ -69,13 +70,37 @@ struct JsonPrintOptions {
// DEPRECATED. Use JsonPrintOptions instead.
typedef JsonPrintOptions JsonOptions;
+// Converts from protobuf message to JSON. This is a simple wrapper of
+// BinaryToJsonString(). It will use the DescriptorPool of the passed-in
+// message to resolve Any types.
+LIBPROTOBUF_EXPORT util::Status MessageToJsonString(const Message& message,
+ string* output,
+ const JsonOptions& options);
+
+inline util::Status MessageToJsonString(const Message& message,
+ string* output) {
+ return MessageToJsonString(message, output, JsonOptions());
+}
+
+// Converts from JSON to protobuf message. This is a simple wrapper of
+// JsonStringToBinary(). It will use the DescriptorPool of the passed-in
+// message to resolve Any types.
+LIBPROTOBUF_EXPORT util::Status JsonStringToMessage(const string& input,
+ Message* message,
+ const JsonParseOptions& options);
+
+inline util::Status JsonStringToMessage(const string& input,
+ Message* message) {
+ return JsonStringToMessage(input, message, JsonParseOptions());
+}
+
// Converts protobuf binary data to JSON.
// The conversion will fail if:
// 1. TypeResolver fails to resolve a type.
// 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.
-util::Status BinaryToJsonStream(
+LIBPROTOBUF_EXPORT util::Status BinaryToJsonStream(
TypeResolver* resolver,
const string& type_url,
io::ZeroCopyInputStream* binary_input,
@@ -110,7 +135,7 @@ inline util::Status BinaryToJsonString(TypeResolver* resolver,
// 1. TypeResolver fails to resolve a type.
// 2. input is not valid JSON format, or conflicts with the type
// information returned by TypeResolver.
-util::Status JsonToBinaryStream(
+LIBPROTOBUF_EXPORT 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 c7d5c59e..24ff5fd6 100644
--- a/src/google/protobuf/util/json_util_test.cc
+++ b/src/google/protobuf/util/json_util_test.cc
@@ -34,6 +34,8 @@
#include <string>
#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor_database.h>
+#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/util/json_format_proto3.pb.h>
#include <google/protobuf/util/type_resolver.h>
#include <google/protobuf/util/type_resolver_util.h>
@@ -63,28 +65,21 @@ static string GetTypeUrl(const Descriptor* message) {
class JsonUtilTest : public testing::Test {
protected:
JsonUtilTest() {
- resolver_.reset(NewTypeResolverForDescriptorPool(
- kTypeUrlPrefix, DescriptorPool::generated_pool()));
}
string ToJson(const Message& message, const JsonPrintOptions& options) {
string result;
- GOOGLE_CHECK_OK(BinaryToJsonString(resolver_.get(),
- GetTypeUrl(message.GetDescriptor()),
- message.SerializeAsString(), &result, options));
+ GOOGLE_CHECK_OK(MessageToJsonString(message, &result, options));
return result;
}
bool FromJson(const string& json, Message* message,
const JsonParseOptions& options) {
- string binary;
- if (!JsonToBinaryString(resolver_.get(),
- GetTypeUrl(message->GetDescriptor()), json, &binary,
- options)
- .ok()) {
- return false;
- }
- return message->ParseFromString(binary);
+ return JsonStringToMessage(json, message, options).ok();
+ }
+
+ bool FromJson(const string& json, Message* message) {
+ return FromJson(json, message, JsonParseOptions());
}
google::protobuf::scoped_ptr<TypeResolver> resolver_;
@@ -133,6 +128,34 @@ TEST_F(JsonUtilTest, TestDefaultValues) {
"\"repeatedMessageValue\":[]"
"}",
ToJson(m, options));
+
+ options.always_print_primitive_fields = true;
+ m.set_string_value("i am a test string value");
+ m.set_bytes_value("i am a test bytes value");
+ EXPECT_EQ(
+ "{\"boolValue\":false,"
+ "\"int32Value\":0,"
+ "\"int64Value\":\"0\","
+ "\"uint32Value\":0,"
+ "\"uint64Value\":\"0\","
+ "\"floatValue\":0,"
+ "\"doubleValue\":0,"
+ "\"stringValue\":\"i am a test string value\","
+ "\"bytesValue\":\"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=\","
+ "\"enumValue\":\"FOO\","
+ "\"repeatedBoolValue\":[],"
+ "\"repeatedInt32Value\":[],"
+ "\"repeatedInt64Value\":[],"
+ "\"repeatedUint32Value\":[],"
+ "\"repeatedUint64Value\":[],"
+ "\"repeatedFloatValue\":[],"
+ "\"repeatedDoubleValue\":[],"
+ "\"repeatedStringValue\":[],"
+ "\"repeatedBytesValue\":[],"
+ "\"repeatedEnumValue\":[],"
+ "\"repeatedMessageValue\":[]"
+ "}",
+ ToJson(m, options));
}
TEST_F(JsonUtilTest, ParseMessage) {
@@ -189,6 +212,45 @@ TEST_F(JsonUtilTest, TestParseErrors) {
EXPECT_FALSE(FromJson("{\"int32Value\":2147483648}", &m, options));
}
+TEST_F(JsonUtilTest, TestDynamicMessage) {
+ // Some random message but good enough to test the wrapper functions.
+ string input =
+ "{\n"
+ " \"int32Value\": 1024,\n"
+ " \"repeatedInt32Value\": [1, 2],\n"
+ " \"messageValue\": {\n"
+ " \"value\": 2048\n"
+ " },\n"
+ " \"repeatedMessageValue\": [\n"
+ " {\"value\": 40}, {\"value\": 96}\n"
+ " ]\n"
+ "}\n";
+
+ // Create a new DescriptorPool with the same protos as the generated one.
+ DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
+ DescriptorPool pool(&database);
+ // A dynamic version of the test proto.
+ DynamicMessageFactory factory;
+ google::protobuf::scoped_ptr<Message> message(factory.GetPrototype(
+ pool.FindMessageTypeByName("proto3.TestMessage"))->New());
+ EXPECT_TRUE(FromJson(input, message.get()));
+
+ // Convert to generated message for easy inspection.
+ TestMessage generated;
+ EXPECT_TRUE(generated.ParseFromString(message->SerializeAsString()));
+ EXPECT_EQ(1024, generated.int32_value());
+ ASSERT_EQ(2, generated.repeated_int32_value_size());
+ EXPECT_EQ(1, generated.repeated_int32_value(0));
+ EXPECT_EQ(2, generated.repeated_int32_value(1));
+ EXPECT_EQ(2048, generated.message_value().value());
+ ASSERT_EQ(2, generated.repeated_message_value_size());
+ EXPECT_EQ(40, generated.repeated_message_value(0).value());
+ EXPECT_EQ(96, generated.repeated_message_value(1).value());
+
+ JsonOptions options;
+ EXPECT_EQ(ToJson(generated, options), ToJson(*message, options));
+}
+
typedef pair<char*, int> Segment;
// A ZeroCopyOutputStream that writes to multiple buffers.
class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream {
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
index a6d0cb07..03a334b6 100644
--- a/src/google/protobuf/util/message_differencer.cc
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -1389,8 +1389,7 @@ bool MessageDifferencer::MatchRepeatedFieldIndices(
// doesn't necessarily imply Compare(b, c). Therefore a naive greedy
// algorithm will fail to find a maximum matching.
// Here we use the argumenting path algorithm.
- MaximumMatcher::NodeMatchCallback* callback =
- ::google::protobuf::internal::NewPermanentCallback(
+ MaximumMatcher::NodeMatchCallback* callback = NewPermanentCallback(
this, &MessageDifferencer::IsMatch,
repeated_field, key_comparator,
&message1, &message2, parent_fields);
diff --git a/src/google/protobuf/util/time_util.cc b/src/google/protobuf/util/time_util.cc
index c782d691..031d019a 100644
--- a/src/google/protobuf/util/time_util.cc
+++ b/src/google/protobuf/util/time_util.cc
@@ -142,6 +142,13 @@ int64 RoundTowardZero(int64 value, int64 divider) {
}
} // namespace
+// Actually define these static const integers. Required by C++ standard (but
+// omitting them may still work with some compilers).
+const int64 TimeUtil::kTimestampMinSeconds;
+const int64 TimeUtil::kTimestampMaxSeconds;
+const int64 TimeUtil::kDurationMaxSeconds;
+const int64 TimeUtil::kDurationMinSeconds;
+
string TimeUtil::ToString(const Timestamp& timestamp) {
return FormatTime(timestamp.seconds(), timestamp.nanos());
}
@@ -174,7 +181,7 @@ string TimeUtil::ToString(const Duration& duration) {
seconds = -seconds;
nanos = -nanos;
}
- result += StringPrintf("%" GOOGLE_LL_FORMAT "d", seconds);
+ result += SimpleItoa(seconds);
if (nanos != 0) {
result += "." + FormatNanos(nanos);
}
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index f2517074..05cc0854 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -466,7 +466,8 @@ void WireFormatLite::WriteGroupMaybeToArray(int field_number,
const int size = value.GetCachedSize();
uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
if (target != NULL) {
- uint8* end = value.SerializeWithCachedSizesToArray(target);
+ uint8* end = value.InternalSerializeWithCachedSizesToArray(
+ output->IsSerializationDeterminstic(), target);
GOOGLE_DCHECK_EQ(end - target, size);
} else {
value.SerializeWithCachedSizes(output);
@@ -482,7 +483,8 @@ void WireFormatLite::WriteMessageMaybeToArray(int field_number,
output->WriteVarint32(size);
uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
if (target != NULL) {
- uint8* end = value.SerializeWithCachedSizesToArray(target);
+ uint8* end = value.InternalSerializeWithCachedSizesToArray(
+ output->IsSerializationDeterminstic(), target);
GOOGLE_DCHECK_EQ(end - target, size);
} else {
value.SerializeWithCachedSizes(output);
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
index ebd858ff..93d7c824 100644
--- a/src/google/protobuf/wire_format_lite_inl.h
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -346,9 +346,9 @@ inline bool WireFormatLite::ReadPackedFixedSizePrimitive(
io::CodedInputStream* input, RepeatedField<CType>* values) {
int length;
if (!input->ReadVarintSizeAsInt(&length)) return false;
- const uint32 old_entries = values->size();
- const uint32 new_entries = length / sizeof(CType);
- const uint32 new_bytes = new_entries * sizeof(CType);
+ const int old_entries = values->size();
+ const int new_entries = length / sizeof(CType);
+ const int new_bytes = new_entries * sizeof(CType);
if (new_bytes != length) return false;
// We would *like* to pre-allocate the buffer to write into (for
// speed), but *must* avoid performing a very large allocation due
@@ -382,7 +382,7 @@ inline bool WireFormatLite::ReadPackedFixedSizePrimitive(
#else
values->Reserve(old_entries + new_entries);
CType value;
- for (uint32 i = 0; i < new_entries; ++i) {
+ for (int i = 0; i < new_entries; ++i) {
if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
values->AddAlreadyReserved(value);
}
@@ -392,7 +392,7 @@ inline bool WireFormatLite::ReadPackedFixedSizePrimitive(
// safely allocate. We read as much as we can into *values
// without pre-allocating "length" bytes.
CType value;
- for (uint32 i = 0; i < new_entries; ++i) {
+ for (int i = 0; i < new_entries; ++i) {
if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
values->Add(value);
}
diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc
index 08490f3f..33a69d3b 100644
--- a/src/google/protobuf/wrappers.pb.cc
+++ b/src/google/protobuf/wrappers.pb.cc
@@ -53,6 +53,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
} // namespace
+void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto() {
protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
const ::google::protobuf::FileDescriptor* file =
@@ -204,6 +205,7 @@ inline void protobuf_AssignDescriptorsOnce() {
&protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto);
}
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
@@ -249,6 +251,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto() {
delete BytesValue_reflection_;
}
+void protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto() {
static bool already_here = false;
if (already_here) return;
@@ -298,16 +301,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fwrappers_2eproto {
}
} static_descriptor_initializer_google_2fprotobuf_2fwrappers_2eproto_;
-namespace {
-
-static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
-static void MergeFromFail(int line) {
- GOOGLE_CHECK(false) << __FILE__ << ":" << line;
-}
-
-} // namespace
-
-
// ===================================================================
#if !defined(_MSC_VER) || _MSC_VER >= 1900
@@ -477,7 +470,9 @@ int DoubleValue::ByteSize() const {
void DoubleValue::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DoubleValue)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const DoubleValue* source =
::google::protobuf::internal::DynamicCastToGenerated<const DoubleValue>(
&from);
@@ -492,7 +487,9 @@ void DoubleValue::MergeFrom(const ::google::protobuf::Message& from) {
void DoubleValue::MergeFrom(const DoubleValue& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DoubleValue)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.value() != 0) {
set_value(from.value());
}
@@ -735,7 +732,9 @@ int FloatValue::ByteSize() const {
void FloatValue::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FloatValue)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const FloatValue* source =
::google::protobuf::internal::DynamicCastToGenerated<const FloatValue>(
&from);
@@ -750,7 +749,9 @@ void FloatValue::MergeFrom(const ::google::protobuf::Message& from) {
void FloatValue::MergeFrom(const FloatValue& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FloatValue)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.value() != 0) {
set_value(from.value());
}
@@ -995,7 +996,9 @@ int Int64Value::ByteSize() const {
void Int64Value::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Int64Value)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const Int64Value* source =
::google::protobuf::internal::DynamicCastToGenerated<const Int64Value>(
&from);
@@ -1010,7 +1013,9 @@ void Int64Value::MergeFrom(const ::google::protobuf::Message& from) {
void Int64Value::MergeFrom(const Int64Value& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Int64Value)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.value() != 0) {
set_value(from.value());
}
@@ -1255,7 +1260,9 @@ int UInt64Value::ByteSize() const {
void UInt64Value::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UInt64Value)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const UInt64Value* source =
::google::protobuf::internal::DynamicCastToGenerated<const UInt64Value>(
&from);
@@ -1270,7 +1277,9 @@ void UInt64Value::MergeFrom(const ::google::protobuf::Message& from) {
void UInt64Value::MergeFrom(const UInt64Value& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UInt64Value)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.value() != 0) {
set_value(from.value());
}
@@ -1515,7 +1524,9 @@ int Int32Value::ByteSize() const {
void Int32Value::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Int32Value)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const Int32Value* source =
::google::protobuf::internal::DynamicCastToGenerated<const Int32Value>(
&from);
@@ -1530,7 +1541,9 @@ void Int32Value::MergeFrom(const ::google::protobuf::Message& from) {
void Int32Value::MergeFrom(const Int32Value& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Int32Value)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.value() != 0) {
set_value(from.value());
}
@@ -1775,7 +1788,9 @@ int UInt32Value::ByteSize() const {
void UInt32Value::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UInt32Value)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const UInt32Value* source =
::google::protobuf::internal::DynamicCastToGenerated<const UInt32Value>(
&from);
@@ -1790,7 +1805,9 @@ void UInt32Value::MergeFrom(const ::google::protobuf::Message& from) {
void UInt32Value::MergeFrom(const UInt32Value& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UInt32Value)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.value() != 0) {
set_value(from.value());
}
@@ -2033,7 +2050,9 @@ int BoolValue::ByteSize() const {
void BoolValue::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.BoolValue)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const BoolValue* source =
::google::protobuf::internal::DynamicCastToGenerated<const BoolValue>(
&from);
@@ -2048,7 +2067,9 @@ void BoolValue::MergeFrom(const ::google::protobuf::Message& from) {
void BoolValue::MergeFrom(const BoolValue& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.BoolValue)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.value() != 0) {
set_value(from.value());
}
@@ -2308,7 +2329,9 @@ int StringValue::ByteSize() const {
void StringValue::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.StringValue)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const StringValue* source =
::google::protobuf::internal::DynamicCastToGenerated<const StringValue>(
&from);
@@ -2323,7 +2346,9 @@ void StringValue::MergeFrom(const ::google::protobuf::Message& from) {
void StringValue::MergeFrom(const StringValue& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.StringValue)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.value().size() > 0) {
set_value(from.value());
}
@@ -2623,7 +2648,9 @@ int BytesValue::ByteSize() const {
void BytesValue::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.BytesValue)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
const BytesValue* source =
::google::protobuf::internal::DynamicCastToGenerated<const BytesValue>(
&from);
@@ -2638,7 +2665,9 @@ void BytesValue::MergeFrom(const ::google::protobuf::Message& from) {
void BytesValue::MergeFrom(const BytesValue& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.BytesValue)
- if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (GOOGLE_PREDICT_FALSE(&from == this)) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ }
if (from.value().size() > 0) {
set_value(from.value());
}
diff --git a/tests.sh b/tests.sh
index 72465a7b..9e95f2b7 100755
--- a/tests.sh
+++ b/tests.sh
@@ -44,6 +44,30 @@ build_cpp() {
build_cpp_distcheck() {
./autogen.sh
./configure
+ make dist
+
+ # List all files that should be included in the distribution package.
+ git ls-files | grep "^\(java\|python\|objectivec\|csharp\|js\|ruby\|cmake\|examples\)" |\
+ grep -v ".gitignore" | grep -v "java/compatibility_tests" > dist.lst
+ # Unzip the dist tar file.
+ DIST=`ls *.tar.gz`
+ tar -xf $DIST
+ cd ${DIST//.tar.gz}
+ # Check if every file exists in the dist tar file.
+ FILES_MISSING=""
+ for FILE in $(<../dist.lst); do
+ if ! file $FILE &>/dev/null; then
+ echo "$FILE is not found!"
+ FILES_MISSING="$FILE $FILES_MISSING"
+ fi
+ done
+ cd ..
+ if [ ! -z "$FILES_MISSING" ]; then
+ echo "Missing files in EXTRA_DIST: $FILES_MISSING"
+ exit 1
+ fi
+
+ # Do the regular dist-check for C++.
make distcheck -j2
}
@@ -57,15 +81,27 @@ build_csharp() {
if [ "$TRAVIS" == "true" ]; then
# Install latest version of Mono
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
+ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1397BC53640DB551
echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
- echo "deb http://download.mono-project.com/repo/debian wheezy-libtiff-compat main" | sudo tee -a /etc/apt/sources.list.d/mono-xamarin.list
sudo apt-get update -qq
sudo apt-get install -qq mono-devel referenceassemblies-pcl nunit
- wget www.nuget.org/NuGet.exe -O nuget.exe
- NUGET=../../nuget.exe
+
+ # Then install the dotnet SDK as per Ubuntu 14.04 instructions on dot.net.
+ sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ trusty main" > /etc/apt/sources.list.d/dotnetdev.list'
+ sudo apt-key adv --keyserver apt-mo.trafficmanager.net --recv-keys 417A0893
+ sudo apt-get update -qq
+ sudo apt-get install -qq dotnet-dev-1.0.0-preview2-003121
fi
- (cd csharp/src; mono $NUGET restore)
+ # Perform "dotnet new" once to get the setup preprocessing out of the
+ # way. That spews a lot of output (including backspaces) into logs
+ # otherwise, and can cause problems. It doesn't matter if this step
+ # is performed multiple times; it's cheap after the first time anyway.
+ mkdir dotnettmp
+ (cd dotnettmp; dotnet new > /dev/null)
+ rm -rf dotnettmp
+
+ (cd csharp/src; dotnet restore)
csharp/buildall.sh
cd conformance && make test_csharp && cd ..
}
@@ -77,10 +113,12 @@ build_golang() {
export PATH="`pwd`/src:$PATH"
# Install Go and the Go protobuf compiler plugin.
- sudo apt-get update -qq
- sudo apt-get install -qq golang
+ on_travis sudo apt-get update -qq
+ on_travis sudo apt-get install -qq golang
+
export GOPATH="$HOME/gocode"
mkdir -p "$GOPATH/src/github.com/google"
+ rm -f "$GOPATH/src/github.com/google/protobuf"
ln -s "`pwd`" "$GOPATH/src/github.com/google/protobuf"
export PATH="$GOPATH/bin:$PATH"
go get github.com/golang/protobuf/protoc-gen-go
@@ -91,13 +129,10 @@ build_golang() {
use_java() {
version=$1
case "$version" in
- jdk6)
- on_travis sudo apt-get install openjdk-6-jdk
- export PATH=/usr/lib/jvm/java-6-openjdk-amd64/bin:$PATH
- ;;
jdk7)
on_travis sudo apt-get install openjdk-7-jdk
export PATH=/usr/lib/jvm/java-7-openjdk-amd64/bin:$PATH
+ export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
;;
oracle7)
if [ "$TRAVIS" == "true" ]; then
@@ -108,6 +143,7 @@ use_java() {
yes | sudo apt-get install oracle-java7-installer
fi;
export PATH=/usr/lib/jvm/java-7-oracle/bin:$PATH
+ export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
;;
esac
@@ -118,6 +154,7 @@ use_java() {
which java
java -version
+ $MVN -version
}
# --batch-mode supresses download progress output that spams the logs.
@@ -150,10 +187,6 @@ build_javanano() {
cd javanano && $MVN test && cd ..
}
-build_java_jdk6() {
- use_java jdk6
- build_java jdk6
-}
build_java_jdk7() {
use_java jdk7
build_java_with_conformance_tests
@@ -162,11 +195,15 @@ build_java_oracle7() {
use_java oracle7
build_java oracle7
}
-
-build_javanano_jdk6() {
- use_java jdk6
- build_javanano
+build_java_compatibility() {
+ use_java jdk7
+ internal_build_cpp
+ # Use the unit-tests extraced from 2.5.0 to test the compatibilty between
+ # 3.0.0-beta-4 and the current version.
+ cd java/compatibility_tests/v2.5.0
+ ./test.sh 3.0.0-beta-4
}
+
build_javanano_jdk7() {
use_java jdk7
build_javanano
@@ -226,6 +263,10 @@ build_objectivec_osx() {
build_objectivec_cocoapods_integration() {
# First, load the RVM environment in bash, needed to update ruby.
source ~/.rvm/scripts/rvm
+ # Update rvm to the latest version. This is needed to solve
+ # https://github.com/google/protobuf/issues/1786 and may not be needed in the
+ # future when Travis updates the default version of rvm.
+ rvm get head
# Update ruby to 2.2.3 as the default one crashes with segmentation faults
# when using pod.
rvm use 2.2.3 --install --binary --fuzzy
@@ -265,14 +306,6 @@ build_python_cpp() {
cd ..
}
-build_ruby19() {
- internal_build_cpp # For conformance tests.
- cd ruby && bash travis-test.sh ruby-1.9 && cd ..
-}
-build_ruby20() {
- internal_build_cpp # For conformance tests.
- cd ruby && bash travis-test.sh ruby-2.0 && cd ..
-}
build_ruby21() {
internal_build_cpp # For conformance tests.
cd ruby && bash travis-test.sh ruby-2.1 && cd ..
@@ -283,7 +316,14 @@ build_ruby22() {
}
build_jruby() {
internal_build_cpp # For conformance tests.
- cd ruby && bash travis-test.sh jruby && cd ..
+ # TODO(xiaofeng): Upgrade to jruby-9.x. There are some broken jests to be
+ # fixed.
+ cd ruby && bash travis-test.sh jruby-1.7 && cd ..
+}
+build_ruby_all() {
+ build_ruby21
+ build_ruby22
+ build_jruby
}
build_javascript() {
@@ -304,11 +344,11 @@ build_javascript() {
if [ "$#" -ne 1 ]; then
echo "
Usage: $0 { cpp |
+ cpp_distcheck |
csharp |
- java_jdk6 |
java_jdk7 |
java_oracle7 |
- javanano_jdk6 |
+ java_compatibility |
javanano_jdk7 |
javanano_oracle7 |
objectivec_ios |
@@ -318,11 +358,10 @@ Usage: $0 { cpp |
objectivec_cocoapods_integration |
python |
python_cpp |
- ruby19 |
- ruby20 |
ruby21 |
ruby22 |
- jruby }
+ jruby |
+ ruby_all)
"
exit 1
fi