aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--BUILD2
-rw-r--r--Makefile.am10
-rw-r--r--WORKSPACE24
-rw-r--r--appveyor.bat2
-rw-r--r--appveyor.yml1
-rw-r--r--benchmarks/readme.txt22
-rw-r--r--cmake/CMakeLists.txt6
-rw-r--r--cmake/extract_includes.bat.in1
-rw-r--r--cmake/install.cmake2
-rw-r--r--cmake/libprotobuf.cmake5
-rw-r--r--cmake/protobuf-config.cmake.in3
-rw-r--r--cmake/protobuf-module.cmake.in1
-rw-r--r--conformance/Makefile.am2
-rw-r--r--conformance/conformance.proto12
-rw-r--r--conformance/conformance_test.cc230
-rw-r--r--conformance/conformance_test.h3
-rw-r--r--conformance/failure_list_cpp.txt12
-rw-r--r--conformance/failure_list_csharp.txt7
-rw-r--r--conformance/failure_list_java.txt8
-rw-r--r--conformance/failure_list_python.txt5
-rw-r--r--conformance/failure_list_python_cpp.txt5
-rw-r--r--conformance/failure_list_ruby.txt14
-rw-r--r--csharp/src/Google.Protobuf.Conformance/Conformance.cs498
-rw-r--r--csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs13
-rw-r--r--docs/third_party.md2
-rw-r--r--editors/protobuf-mode.el3
-rwxr-xr-xgenerate_descriptor_proto.sh2
-rw-r--r--gmock.BUILD20
-rw-r--r--java/util/src/main/java/com/google/protobuf/util/JsonFormat.java28
-rw-r--r--java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java16
-rw-r--r--javanano/pom.xml4
-rw-r--r--js/README.md3
-rwxr-xr-xobjectivec/DevTools/compile_testing_protos.sh91
-rw-r--r--objectivec/GPBArray.m20
-rw-r--r--objectivec/GPBBootstrap.h2
-rw-r--r--objectivec/GPBCodedOutputStream.m2
-rw-r--r--objectivec/GPBDescriptor.h9
-rw-r--r--objectivec/GPBDescriptor.m114
-rw-r--r--objectivec/GPBDescriptor_PackagePrivate.h8
-rw-r--r--objectivec/GPBUtilities_PackagePrivate.h8
-rw-r--r--objectivec/GPBWellKnownTypes.h141
-rw-r--r--objectivec/GPBWellKnownTypes.m135
-rw-r--r--objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj6
-rw-r--r--objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj6
-rw-r--r--objectivec/Tests/GPBDescriptorTests.m29
-rw-r--r--objectivec/Tests/GPBMessageTests+Runtime.m143
-rw-r--r--objectivec/Tests/GPBUnittestProtos.m9
-rw-r--r--objectivec/Tests/GPBUnittestProtos2.m34
-rw-r--r--objectivec/Tests/GPBWellKnownTypesTest.m56
-rw-r--r--objectivec/Tests/unittest_cycle.proto6
-rw-r--r--objectivec/Tests/unittest_extension_chain_a.proto51
-rw-r--r--objectivec/Tests/unittest_extension_chain_b.proto47
-rw-r--r--objectivec/Tests/unittest_extension_chain_c.proto45
-rw-r--r--objectivec/Tests/unittest_extension_chain_d.proto49
-rw-r--r--objectivec/Tests/unittest_extension_chain_e.proto40
-rw-r--r--objectivec/Tests/unittest_extension_chain_f.proto44
-rw-r--r--objectivec/Tests/unittest_extension_chain_g.proto41
-rw-r--r--objectivec/google/protobuf/Any.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/Any.pbobjc.m8
-rw-r--r--objectivec/google/protobuf/Api.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/Api.pbobjc.m29
-rw-r--r--objectivec/google/protobuf/Duration.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/Duration.pbobjc.m6
-rw-r--r--objectivec/google/protobuf/Empty.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/Empty.pbobjc.m6
-rw-r--r--objectivec/google/protobuf/FieldMask.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/FieldMask.pbobjc.m6
-rw-r--r--objectivec/google/protobuf/SourceContext.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/SourceContext.pbobjc.m6
-rw-r--r--objectivec/google/protobuf/Struct.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/Struct.pbobjc.m12
-rw-r--r--objectivec/google/protobuf/Timestamp.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/Timestamp.pbobjc.m6
-rw-r--r--objectivec/google/protobuf/Type.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/Type.pbobjc.m35
-rw-r--r--objectivec/google/protobuf/Wrappers.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/Wrappers.pbobjc.m22
-rw-r--r--protobuf.bzl58
-rwxr-xr-xpython/google/protobuf/internal/reflection_test.py2
-rw-r--r--python/google/protobuf/json_format.py2
-rw-r--r--ruby/lib/google/protobuf.rb2
-rw-r--r--ruby/lib/google/protobuf/well_known_types.rb212
-rw-r--r--ruby/tests/basic.rb4
-rw-r--r--ruby/tests/well_known_types_test.rb122
-rw-r--r--src/google/protobuf/api.pb.cc2
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc5
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc4
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc2
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_extension.cc2
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_field.cc2
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_file.cc437
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_file.h15
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_generator.cc51
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_generator.h11
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers.cc363
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers.h61
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_map_field.cc2
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_message.cc16
-rw-r--r--src/google/protobuf/compiler/parser.cc1
-rw-r--r--src/google/protobuf/compiler/subprocess.cc12
-rw-r--r--src/google/protobuf/descriptor.pb.cc18
-rw-r--r--src/google/protobuf/duration.pb.cc2
-rw-r--r--src/google/protobuf/stubs/atomicops_internals_generic_gcc.h18
-rw-r--r--src/google/protobuf/stubs/callback.h4
-rw-r--r--src/google/protobuf/stubs/common_unittest.cc2
-rw-r--r--src/google/protobuf/stubs/map_util.h7
-rw-r--r--src/google/protobuf/stubs/once_unittest.cc5
-rw-r--r--src/google/protobuf/testing/file.cc17
-rw-r--r--src/google/protobuf/timestamp.pb.cc2
-rw-r--r--src/google/protobuf/type.pb.cc2
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter.cc5
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter.cc2
-rw-r--r--src/google/protobuf/util/json_util_test.cc28
-rw-r--r--src/google/protobuf/util/message_differencer.cc3
115 files changed, 3043 insertions, 725 deletions
diff --git a/.gitignore b/.gitignore
index 5cb8cba9..052dd14d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -64,6 +64,8 @@ src/protoc
src/unittest_proto_middleman
# Generated test scaffolding
+src/no_warning_test.cc
+src/no-warning-test
src/protobuf*-test
src/test_plugin
src/testzip.*
@@ -108,8 +110,11 @@ conformance/conformance.pb.cc
conformance/conformance.pb.h
conformance/Conformance.pbobjc.h
conformance/Conformance.pbobjc.m
-conformance/conformance.rb
+conformance/conformance_pb.rb
+conformance/failing_tests.txt
conformance/google/
conformance/javac_middleman
conformance/lite/
+conformance/nonexistent_tests.txt
conformance/protoc_middleman
+conformance/succeeding_tests.txt
diff --git a/BUILD b/BUILD
index 0941d8c4..941ca691 100644
--- a/BUILD
+++ b/BUILD
@@ -2,6 +2,8 @@
licenses(["notice"])
+exports_files(["LICENSE"])
+
################################################################################
# Protobuf Runtime Library
################################################################################
diff --git a/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= \
diff --git a/WORKSPACE b/WORKSPACE
index 065dc819..df919ad1 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,15 +1,15 @@
-new_http_archive(
- name = "gmock_archive",
- url = "https://googlemock.googlecode.com/files/gmock-1.7.0.zip",
- sha256 = "26fcbb5925b74ad5fc8c26b0495dfc96353f4d553492eb97e85a8a6d2f43095b",
+new_git_repository(
+ name = "googletest",
build_file = "gmock.BUILD",
+ remote = "https://github.com/google/googletest",
+ tag = "release-1.8.0",
)
new_http_archive(
name = "six_archive",
- url = "https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz#md5=34eed507548117b2ab523ab14b2f8b55",
- sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a",
build_file = "six.BUILD",
+ sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a",
+ url = "https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz#md5=34eed507548117b2ab523ab14b2f8b55",
)
bind(
@@ -19,12 +19,12 @@ bind(
bind(
name = "gtest",
- actual = "@gmock_archive//:gtest",
+ actual = "@googletest//:gtest",
)
bind(
name = "gtest_main",
- actual = "@gmock_archive//:gtest_main",
+ actual = "@googletest//:gtest_main",
)
bind(
@@ -33,8 +33,8 @@ bind(
)
maven_jar(
- name = "guava_maven",
- artifact = "com.google.guava:guava:18.0",
+ name = "guava_maven",
+ artifact = "com.google.guava:guava:18.0",
)
bind(
@@ -43,8 +43,8 @@ bind(
)
maven_jar(
- name = "gson_maven",
- artifact = "com.google.code.gson:gson:2.3",
+ name = "gson_maven",
+ artifact = "com.google.code.gson:gson:2.3",
)
bind(
diff --git a/appveyor.bat b/appveyor.bat
index 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);