diff options
115 files changed, 3043 insertions, 725 deletions
@@ -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 @@ -2,6 +2,8 @@ licenses(["notice"]) +exports_files(["LICENSE"]) + ################################################################################ # Protobuf Runtime Library ################################################################################ diff --git a/Makefile.am b/Makefile.am index c2d98048..a4de1bd3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -534,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 \ @@ -555,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 \ @@ -682,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 \ @@ -708,6 +717,7 @@ ruby_EXTRA_DIST= \ 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= \ @@ -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 0e6dd520..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 diff --git a/appveyor.yml b/appveyor.yml index 2ea3cb78..20fc8ade 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,6 +11,7 @@ environment: matrix: - language: cpp BUILD_DLL: ON + UNICODE: ON - language: csharp 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/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.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/conformance/Makefile.am b/conformance/Makefile.am index b76407ee..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 \ 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_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_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/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/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/docs/third_party.md b/docs/third_party.md index 021cc564..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 @@ -63,6 +64,7 @@ These are projects we know about implementing Protocol Buffers for other program * OCaml: http://piqi.org/ * Perl: http://groups.google.com/group/protobuf-perl * Perl: http://search.cpan.org/perldoc?Google::ProtocolBuffers +* Perl: https://metacpan.org/pod/Google::ProtocolBuffers::Dynamic * Perl/XS: http://code.google.com/p/protobuf-perlxs/ * PHP: http://code.google.com/p/pb4php/ * PHP: https://github.com/allegro/php-protobuf/ 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/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/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java index ad50cc0e..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 @@ -224,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); } /** @@ -232,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; } /** @@ -247,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); } /** @@ -259,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); } /** @@ -272,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); } } @@ -1024,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(); } @@ -1191,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 6fc784ef..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 @@ -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)); diff --git a/javanano/pom.xml b/javanano/pom.xml index e6a03d15..6ebba3cf 100644 --- a/javanano/pom.xml +++ b/javanano/pom.xml @@ -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-7</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/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/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.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 2e5bdc71..7dc943d4 100644 --- a/objectivec/GPBBootstrap.h +++ b/objectivec/GPBBootstrap.h @@ -99,4 +99,4 @@ // regenerated. // // Meant to be used internally by generated code. -#define GOOGLE_PROTOBUF_OBJC_GEN_VERSION 30001 +#define GOOGLE_PROTOBUF_OBJC_GEN_VERSION 30002 diff --git a/objectivec/GPBCodedOutputStream.m b/objectivec/GPBCodedOutputStream.m index 251a159c..7c3ab447 100644 --- a/objectivec/GPBCodedOutputStream.m +++ b/objectivec/GPBCodedOutputStream.m @@ -290,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]; } diff --git a/objectivec/GPBDescriptor.h b/objectivec/GPBDescriptor.h index 36fb4eae..651f4de0 100644 --- a/objectivec/GPBDescriptor.h +++ b/objectivec/GPBDescriptor.h @@ -81,6 +81,13 @@ typedef NS_ENUM(uint8_t, GPBFieldType) { @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. @@ -118,6 +125,8 @@ typedef NS_ENUM(uint8_t, GPBFieldType) { /** 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; 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/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 96d51d9e..90d96c6f 100644 --- a/objectivec/GPBWellKnownTypes.h +++ b/objectivec/GPBWellKnownTypes.h @@ -37,15 +37,32 @@ #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 +#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. **/ @@ -54,7 +71,12 @@ NS_ASSUME_NONNULL_BEGIN /** The NSDate representation of this GPBTimestamp. */ @property(nonatomic, readwrite, strong) NSDate *date; -/** The NSTimeInterval representation of this GPBTimestamp. */ +/** + * 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; /** @@ -77,12 +99,19 @@ NS_ASSUME_NONNULL_BEGIN @end +#pragma mark - GPBDuration + /** * Category for GPBDuration to work with standard Foundation time type. **/ @interface GPBDuration (GBPWellKnownTypes) -/** The NSTimeInterval representation of this GPBTimestamp. */ +/** + * 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; /** @@ -90,10 +119,116 @@ NS_ASSUME_NONNULL_BEGIN * * @param timeIntervalSince1970 Time interval to configure the GPBDuration with. * - * @return A newly initialized GPBTimestamp. + * @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/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 60844c94..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() } 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/objectivec/Tests/GPBUnittestProtos2.m b/objectivec/Tests/GPBUnittestProtos2.m new file mode 100644 index 00000000..ef9f0702 --- /dev/null +++ b/objectivec/Tests/GPBUnittestProtos2.m @@ -0,0 +1,34 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2016 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// 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/google/protobuf/Any.pbobjc.h b/objectivec/google/protobuf/Any.pbobjc.h index 842052fe..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 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 182e866c..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 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 fa91e223..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 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 4d36174d..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 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 491463f9..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 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 d9450057..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 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 a5b31cd0..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 diff --git a/objectivec/google/protobuf/Struct.pbobjc.m b/objectivec/google/protobuf/Struct.pbobjc.m index 8ea1f124..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", }; @@ -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 ebfa670f..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 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 05411958..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 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 e397c480..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 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/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py index 20e5d245..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) 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/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/tests/basic.rb b/ruby/tests/basic.rb index f81e456c..8b6d329e 100644 --- a/ruby/tests/basic.rb +++ b/ruby/tests/basic.rb @@ -468,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 } 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/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc index 131ca206..d7fb644c 100644 --- a/src/google/protobuf/api.pb.cc +++ b/src/google/protobuf/api.pb.cc @@ -1006,7 +1006,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) 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_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index aa00962e..0034b121 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++) { @@ -2956,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/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc index c0e7253a..d0de1eca 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc @@ -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 d2a6e882..527b7c0c 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc @@ -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); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index 438f4113..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 - 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(); +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); } @@ -406,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); } } @@ -460,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" @@ -495,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" @@ -512,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(); @@ -528,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" @@ -556,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(); @@ -584,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 a0b6d6cb..36407467 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc @@ -45,10 +45,22 @@ 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. These options are passed to the compiler using the // --objc_opt flag. The options are passed as a comma separated list of @@ -117,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 9ddca574..b1723318 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.h @@ -51,8 +51,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 4a94373a..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,17 +853,21 @@ 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; } @@ -979,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... @@ -1021,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). @@ -1063,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()) { @@ -1070,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() { } @@ -1399,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 c96d5ea5..316069e1 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -69,6 +69,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. @@ -85,6 +88,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 @@ -139,6 +143,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()) { @@ -170,7 +180,7 @@ 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 HeaderDoc/appledoc style comments out of the comments in the .proto // file. @@ -187,12 +197,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. @@ -227,6 +237,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 822da893..4c6e1b55 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc @@ -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/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/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 26494b6d..56c3b7fb 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -2535,7 +2535,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) @@ -2839,7 +2839,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) @@ -7357,7 +7357,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) @@ -8174,7 +8174,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) @@ -9582,7 +9582,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) @@ -10196,7 +10196,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) @@ -11192,7 +11192,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) @@ -13053,7 +13053,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) @@ -14941,7 +14941,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) diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc index f916000e..884f6ccb 100644 --- a/src/google/protobuf/duration.pb.cc +++ b/src/google/protobuf/duration.pb.cc @@ -185,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) 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/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/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/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc index 0a18edbe..e6c9c58b 100644 --- a/src/google/protobuf/timestamp.pb.cc +++ b/src/google/protobuf/timestamp.pb.cc @@ -199,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) diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc index 87a7864f..fc7d5332 100644 --- a/src/google/protobuf/type.pb.cc +++ b/src/google/protobuf/type.pb.cc @@ -1126,7 +1126,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) diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc index 1e8dab70..fa31f763 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter.cc +++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc @@ -165,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; } 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_test.cc b/src/google/protobuf/util/json_util_test.cc index dacac5e0..24ff5fd6 100644 --- a/src/google/protobuf/util/json_util_test.cc +++ b/src/google/protobuf/util/json_util_test.cc @@ -128,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) { 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); |