diff options
103 files changed, 1986 insertions, 941 deletions
diff --git a/.travis.yml b/.travis.yml index 7780174c..7daee86b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,9 +66,5 @@ matrix: env: CONFIG=ruby22 - os: osx env: CONFIG=jruby - # Travis seems be flaky in letting the iOS simulator launch, so keep that - # flake from failing builds by marking that build as an allowed failure. - - os: osx - env: CONFIG=objectivec_ios notifications: email: false @@ -54,9 +54,9 @@ cc_library( "src/google/protobuf/stubs/time.cc", "src/google/protobuf/wire_format_lite.cc", ], + hdrs = glob(["src/google/protobuf/**/*.h"]), copts = COPTS, includes = ["src/"], - hdrs = glob(["src/google/protobuf/**/*.h"]), linkopts = LINK_OPTS, visibility = ["//visibility:public"], ) @@ -156,9 +156,9 @@ cc_proto_library( name = "cc_wkt_protos", srcs = WELL_KNOWN_PROTOS, include = "src", + default_runtime = ":protobuf", internal_bootstrap_hack = 1, protoc = ":protoc", - default_runtime = ":protobuf", visibility = ["//visibility:public"], ) @@ -336,8 +336,8 @@ cc_proto_library( name = "cc_test_protos", srcs = LITE_TEST_PROTOS + TEST_PROTOS, include = "src", - protoc = ":protoc", default_runtime = ":protobuf", + protoc = ":protoc", deps = [":cc_wkt_protos"], ) @@ -509,14 +509,66 @@ internal_copied_filegroup( include = "python", ) +cc_binary( + name = "internal/_api_implementation.so", + srcs = ["python/google/protobuf/internal/api_implementation.cc"], + copts = COPTS + [ + "-DPYTHON_PROTO2_CPP_IMPL_V2", + ], + linkshared = 1, + linkstatic = 1, + deps = select({ + "//conditions:default": [], + ":use_fast_cpp_protos": ["//util/python:python_headers"], + }), +) + +cc_binary( + name = "pyext/_message.so", + srcs = glob([ + "python/google/protobuf/pyext/*.cc", + "python/google/protobuf/pyext/*.h", + ]), + copts = COPTS + [ + "-DGOOGLE_PROTOBUF_HAS_ONEOF=1", + ], + includes = [ + "python/", + "src/", + ], + linkshared = 1, + linkstatic = 1, + deps = [ + ":protobuf", + ] + select({ + "//conditions:default": [], + ":use_fast_cpp_protos": ["//util/python:python_headers"], + }), +) + +config_setting( + name = "use_fast_cpp_protos", + values = { + "define": "use_fast_cpp_protos=true", + }, +) + py_proto_library( name = "protobuf_python", srcs = WELL_KNOWN_PROTOS, include = "src", + data = select({ + "//conditions:default": [], + ":use_fast_cpp_protos": [ + ":internal/_api_implementation.so", + ":pyext/_message.so", + ], + }), + default_runtime = "", protoc = ":protoc", py_extra_srcs = [":python_srcs"], py_libs = ["//external:six"], - default_runtime = "", + srcs_version = "PY2AND3", visibility = ["//visibility:public"], ) @@ -535,9 +587,9 @@ py_proto_library( name = "python_common_test_protos", srcs = LITE_TEST_PROTOS + TEST_PROTOS, include = "src", + default_runtime = "", protoc = ":protoc", deps = [":protobuf_python"], - default_runtime = "", ) py_proto_library( @@ -547,14 +599,15 @@ py_proto_library( "python/google/protobuf/internal/import_test_package/*.proto", ]), include = "python", + default_runtime = ":protobuf_python", protoc = ":protoc", deps = [":python_common_test_protos"], - default_runtime = ":protobuf_python", ) py_library( name = "python_tests", srcs = [":python_test_srcs"], + srcs_version = "PY2AND3", deps = [ ":protobuf_python", ":python_common_test_protos", diff --git a/Makefile.am b/Makefile.am index 8657f821..bb735177 100644 --- a/Makefile.am +++ b/Makefile.am @@ -682,6 +682,7 @@ EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \ # Deletes all the files generated by autogen.sh. MAINTAINERCLEANFILES = \ aclocal.m4 \ + ar-lib \ config.guess \ config.sub \ configure \ diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 9de6341a..15ae457a 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -115,6 +115,8 @@ else (protobuf_BUILD_SHARED_LIBS) endif (protobuf_BUILD_SHARED_LIBS) if (MSVC) + # Build with multiple processes + add_definitions(/MP) add_definitions(/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305) string(REPLACE "/" "\\" PROTOBUF_SOURCE_WIN32_PATH ${protobuf_SOURCE_DIR}) string(REPLACE "/" "\\" PROTOBUF_BINARY_WIN32_PATH ${protobuf_BINARY_DIR}) diff --git a/conformance/Makefile.am b/conformance/Makefile.am index d7bb9397..1c022270 100644 --- a/conformance/Makefile.am +++ b/conformance/Makefile.am @@ -10,6 +10,7 @@ protoc_outputs = \ other_language_protoc_outputs = \ conformance.rb \ com/google/protobuf/conformance/Conformance.java \ + conformance_pb2.py \ Conformance.pbobjc.h \ Conformance.pbobjc.m @@ -38,7 +39,11 @@ bin_PROGRAMS += conformance-objc conformance_objc_SOURCES = conformance_objc.m ../objectivec/GPBProtocolBuffers.m nodist_conformance_objc_SOURCES = Conformance.pbobjc.m -conformance_objc_CPPFLAGS = -I$(top_srcdir)/objectivec +# On travis, the build fails without the isysroot because whatever system +# headers are being found don't include generics support for +# NSArray/NSDictionary, the only guess is their image at one time had an odd +# setup for Xcode and old frameworks are being found. +conformance_objc_CPPFLAGS = -I$(top_srcdir)/objectivec -isysroot `xcrun --sdk macosx --show-sdk-path` conformance_objc_LDFLAGS = -framework Foundation # Explicit dep beacuse BUILT_SOURCES are only done before a "make all/check" # so a direct "make test_objc" could fail if parallel enough. @@ -49,7 +54,7 @@ endif if USE_EXTERNAL_PROTOC protoc_middleman: $(protoc_inputs) - $(PROTOC) -I$(srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. $^ + $(PROTOC) -I$(srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. --python_out=.$^ touch protoc_middleman else @@ -58,7 +63,7 @@ else # relative to srcdir, which may not be the same as the current directory when # building out-of-tree. protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(protoc_inputs) - oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --objc_out=$$oldpwd $(protoc_inputs) ) + oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --objc_out=$$oldpwd --python_out=$$oldpwd $(protoc_inputs) ) touch protoc_middleman endif @@ -106,6 +111,14 @@ test_csharp: protoc_middleman conformance-test-runner conformance-csharp test_ruby: protoc_middleman conformance-test-runner $(other_language_protoc_outputs) RUBYLIB=../ruby/lib:. ./conformance-test-runner --failure_list failure_list_ruby.txt ./conformance_ruby.rb +# These depend on library paths being properly set up. The easiest way to +# run them is to just use "tox" from the python dir. +test_python: protoc_middleman conformance-test-runner + ./conformance-test-runner --failure_list failure_list_python.txt ./conformance_python.py + +test_python_cpp: protoc_middleman conformance-test-runner + ./conformance-test-runner --failure_list failure_list_python_cpp.txt ./conformance_python.py + if OBJC_CONFORMANCE_TEST test_objc: protoc_middleman conformance-test-runner conformance-objc diff --git a/conformance/conformance_python.py b/conformance/conformance_python.py new file mode 100755 index 00000000..a490c8e8 --- /dev/null +++ b/conformance/conformance_python.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python +# +# 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. + +"""A conformance test implementation for the Python protobuf library. + +See conformance.proto for more information. +""" + +import struct +import sys +import os +from google.protobuf import message +from google.protobuf import json_format +import conformance_pb2 + +sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0) +sys.stdin = os.fdopen(sys.stdin.fileno(), 'rb', 0) + +test_count = 0 +verbose = False + +class ProtocolError(Exception): + pass + +def do_test(request): + test_message = conformance_pb2.TestAllTypes() + response = conformance_pb2.ConformanceResponse() + test_message = conformance_pb2.TestAllTypes() + + try: + if request.WhichOneof('payload') == 'protobuf_payload': + try: + test_message.ParseFromString(request.protobuf_payload) + except message.DecodeError as e: + response.parse_error = str(e) + return response + + elif request.WhichOneof('payload') == 'json_payload': + try: + json_format.Parse(request.json_payload, test_message) + except json_format.ParseError as e: + response.parse_error = str(e) + return response + + else: + raise ProtocolError("Request didn't have payload.") + + if request.requested_output_format == conformance_pb2.UNSPECIFIED: + raise ProtocolError("Unspecified output format") + + elif request.requested_output_format == conformance_pb2.PROTOBUF: + response.protobuf_payload = test_message.SerializeToString() + + elif request.requested_output_format == conformance_pb2.JSON: + response.json_payload = json_format.MessageToJson(test_message) + + except Exception as e: + response.runtime_error = str(e) + + return response + +def do_test_io(): + length_bytes = sys.stdin.read(4) + if len(length_bytes) == 0: + return False # EOF + elif len(length_bytes) != 4: + raise IOError("I/O error") + + # "I" is "unsigned int", so this depends on running on a platform with + # 32-bit "unsigned int" type. The Python struct module unfortunately + # has no format specifier for uint32_t. + length = struct.unpack("<I", length_bytes)[0] + serialized_request = sys.stdin.read(length) + if len(serialized_request) != length: + raise IOError("I/O error") + + request = conformance_pb2.ConformanceRequest() + request.ParseFromString(serialized_request) + + response = do_test(request) + + serialized_response = response.SerializeToString() + sys.stdout.write(struct.pack("<I", len(serialized_response))) + sys.stdout.write(serialized_response) + sys.stdout.flush() + + if verbose: + sys.stderr.write("conformance_python: request=%s, response=%s\n" % ( + request.ShortDebugString().c_str(), + response.ShortDebugString().c_str())) + + global test_count + test_count += 1 + + return True + +while True: + if not do_test_io(): + sys.stderr.write("conformance_python: received EOF from test runner " + + "after %s tests, exiting\n" % (test_count)) + sys.exit(0) diff --git a/conformance/conformance_test.cc b/conformance/conformance_test.cc index 0ee201f3..c250cb1e 100644 --- a/conformance/conformance_test.cc +++ b/conformance/conformance_test.cc @@ -514,9 +514,11 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, "These tests succeeded, even though they were listed in " "the failure list. Remove them from the failure list"); - CheckSetEmpty(skipped_, - "These tests were skipped (probably because support for some " - "features is not implemented)"); + if (verbose_) { + CheckSetEmpty(skipped_, + "These tests were skipped (probably because support for some " + "features is not implemented)"); + } StringAppendF(&output_, "CONFORMANCE SUITE %s: %d successes, %d skipped, " diff --git a/conformance/conformance_test_runner.cc b/conformance/conformance_test_runner.cc index 780e1c44..c3b3db22 100644 --- a/conformance/conformance_test_runner.cc +++ b/conformance/conformance_test_runner.cc @@ -202,6 +202,12 @@ void UsageError() { void ParseFailureList(const char *filename, vector<string>* failure_list) { std::ifstream infile(filename); + + if (!infile.is_open()) { + fprintf(stderr, "Couldn't open failure list file: %s\n", filename); + exit(1); + } + for (string line; getline(infile, line);) { // Remove whitespace. line.erase(std::remove_if(line.begin(), line.end(), ::isspace), diff --git a/conformance/failure_list_python.txt b/conformance/failure_list_python.txt new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/conformance/failure_list_python.txt diff --git a/conformance/failure_list_python_cpp.txt b/conformance/failure_list_python_cpp.txt new file mode 100644 index 00000000..4b16a88b --- /dev/null +++ b/conformance/failure_list_python_cpp.txt @@ -0,0 +1,25 @@ +# This is the list of conformance tests that are known to fail for the +# Python/C++ implementation right now. These should be fixed. +# +# By listing them here we can keep tabs on which ones are failing and be sure +# that we don't introduce regressions in other tests. +# +# TODO(haberman): insert links to corresponding bugs tracking the issue. +# Should we use GitHub issues or the Google-internal bug tracker? + +ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE +ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE +ProtobufInput.PrematureEofInPackedField.BOOL +ProtobufInput.PrematureEofInPackedField.DOUBLE +ProtobufInput.PrematureEofInPackedField.ENUM +ProtobufInput.PrematureEofInPackedField.FIXED32 +ProtobufInput.PrematureEofInPackedField.FIXED64 +ProtobufInput.PrematureEofInPackedField.FLOAT +ProtobufInput.PrematureEofInPackedField.INT32 +ProtobufInput.PrematureEofInPackedField.INT64 +ProtobufInput.PrematureEofInPackedField.SFIXED32 +ProtobufInput.PrematureEofInPackedField.SFIXED64 +ProtobufInput.PrematureEofInPackedField.SINT32 +ProtobufInput.PrematureEofInPackedField.SINT64 +ProtobufInput.PrematureEofInPackedField.UINT32 +ProtobufInput.PrematureEofInPackedField.UINT64 diff --git a/csharp/src/AddressBook/Addressbook.cs b/csharp/src/AddressBook/Addressbook.cs index d5455d80..2c81004c 100644 --- a/csharp/src/AddressBook/Addressbook.cs +++ b/csharp/src/AddressBook/Addressbook.cs @@ -43,6 +43,9 @@ namespace Google.Protobuf.Examples.AddressBook { } #region Messages + /// <summary> + /// [START messages] + /// </summary> [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public sealed partial class Person : pb::IMessage<Person> { private static readonly pb::MessageParser<Person> _parser = new pb::MessageParser<Person>(() => new Person()); @@ -143,7 +146,7 @@ namespace Google.Protobuf.Examples.AddressBook { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -302,7 +305,7 @@ namespace Google.Protobuf.Examples.AddressBook { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -426,7 +429,7 @@ namespace Google.Protobuf.Examples.AddressBook { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf.Conformance/Conformance.cs b/csharp/src/Google.Protobuf.Conformance/Conformance.cs index 50ce1de4..f135d768 100644 --- a/csharp/src/Google.Protobuf.Conformance/Conformance.cs +++ b/csharp/src/Google.Protobuf.Conformance/Conformance.cs @@ -284,7 +284,7 @@ namespace Conformance { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -532,7 +532,7 @@ namespace Conformance { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1544,7 +1544,7 @@ namespace Conformance { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2343,7 +2343,7 @@ namespace Conformance { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2471,7 +2471,7 @@ namespace Conformance { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf.Conformance/Program.cs b/csharp/src/Google.Protobuf.Conformance/Program.cs index af92da9f..8f72c8f9 100644 --- a/csharp/src/Google.Protobuf.Conformance/Program.cs +++ b/csharp/src/Google.Protobuf.Conformance/Program.cs @@ -31,6 +31,7 @@ #endregion using Conformance; +using Google.Protobuf.Reflection; using System; using System.IO; @@ -47,16 +48,17 @@ namespace Google.Protobuf.Conformance // This way we get the binary streams instead of readers/writers. var input = new BinaryReader(Console.OpenStandardInput()); var output = new BinaryWriter(Console.OpenStandardOutput()); + var typeRegistry = TypeRegistry.FromMessages(TestAllTypes.Descriptor); int count = 0; - while (RunTest(input, output)) + while (RunTest(input, output, typeRegistry)) { count++; } Console.Error.WriteLine("Received EOF after {0} tests", count); } - private static bool RunTest(BinaryReader input, BinaryWriter output) + private static bool RunTest(BinaryReader input, BinaryWriter output, TypeRegistry typeRegistry) { int? size = ReadInt32(input); if (size == null) @@ -69,7 +71,7 @@ namespace Google.Protobuf.Conformance throw new EndOfStreamException("Read " + inputData.Length + " bytes of data when expecting " + size); } ConformanceRequest request = ConformanceRequest.Parser.ParseFrom(inputData); - ConformanceResponse response = PerformRequest(request); + ConformanceResponse response = PerformRequest(request, typeRegistry); byte[] outputData = response.ToByteArray(); output.Write(outputData.Length); output.Write(outputData); @@ -77,30 +79,33 @@ namespace Google.Protobuf.Conformance return true; } - private static ConformanceResponse PerformRequest(ConformanceRequest request) + private static ConformanceResponse PerformRequest(ConformanceRequest request, TypeRegistry typeRegistry) { TestAllTypes message; - switch (request.PayloadCase) + try { - case ConformanceRequest.PayloadOneofCase.JsonPayload: - return new ConformanceResponse { Skipped = "JSON parsing not implemented in C# yet" }; - case ConformanceRequest.PayloadOneofCase.ProtobufPayload: - try - { + switch (request.PayloadCase) + { + case ConformanceRequest.PayloadOneofCase.JsonPayload: + var parser = new JsonParser(new JsonParser.Settings(20, typeRegistry)); + message = parser.Parse<TestAllTypes>(request.JsonPayload); + break; + case ConformanceRequest.PayloadOneofCase.ProtobufPayload: message = TestAllTypes.Parser.ParseFrom(request.ProtobufPayload); - } - catch (InvalidProtocolBufferException e) - { - return new ConformanceResponse { ParseError = e.Message }; - } - break; - default: - throw new Exception("Unsupported request payload: " + request.PayloadCase); + break; + default: + throw new Exception("Unsupported request payload: " + request.PayloadCase); + } + } + catch (InvalidProtocolBufferException e) + { + return new ConformanceResponse { ParseError = e.Message }; } switch (request.RequestedOutputFormat) { case global::Conformance.WireFormat.JSON: - return new ConformanceResponse { JsonPayload = JsonFormatter.Default.Format(message) }; + var formatter = new JsonFormatter(new JsonFormatter.Settings(false, typeRegistry)); + return new ConformanceResponse { JsonPayload = formatter.Format(message) }; case global::Conformance.WireFormat.PROTOBUF: return new ConformanceResponse { ProtobufPayload = message.ToByteString() }; default: diff --git a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs index 08cedad8..8473b4be 100644 --- a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs @@ -35,6 +35,7 @@ using Google.Protobuf.TestProtos; using NUnit.Framework; using UnitTest.Issues.TestProtos; using Google.Protobuf.WellKnownTypes; +using Google.Protobuf.Reflection; namespace Google.Protobuf { @@ -420,6 +421,47 @@ namespace Google.Protobuf AssertJson("{ 'fileName': 'foo.proto' }", JsonFormatter.Default.Format(message)); } + [Test] + public void AnyWellKnownType() + { + var formatter = new JsonFormatter(new JsonFormatter.Settings(false, TypeRegistry.FromMessages(Timestamp.Descriptor))); + var timestamp = new DateTime(1673, 6, 19, 12, 34, 56, DateTimeKind.Utc).ToTimestamp(); + var any = Any.Pack(timestamp); + AssertJson("{ '@type': 'type.googleapis.com/google.protobuf.Timestamp', 'value': '1673-06-19T12:34:56Z' }", formatter.Format(any)); + } + + [Test] + public void AnyMessageType() + { + var formatter = new JsonFormatter(new JsonFormatter.Settings(false, TypeRegistry.FromMessages(TestAllTypes.Descriptor))); + var message = new TestAllTypes { SingleInt32 = 10, SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 } }; + var any = Any.Pack(message); + AssertJson("{ '@type': 'type.googleapis.com/protobuf_unittest.TestAllTypes', 'singleInt32': 10, 'singleNestedMessage': { 'bb': 20 } }", formatter.Format(any)); + } + + [Test] + public void AnyNested() + { + var registry = TypeRegistry.FromMessages(TestWellKnownTypes.Descriptor, TestAllTypes.Descriptor); + var formatter = new JsonFormatter(new JsonFormatter.Settings(false, registry)); + + // Nest an Any as the value of an Any. + var doubleNestedMessage = new TestAllTypes { SingleInt32 = 20 }; + var nestedMessage = Any.Pack(doubleNestedMessage); + var message = new TestWellKnownTypes { AnyField = Any.Pack(nestedMessage) }; + AssertJson("{ 'anyField': { '@type': 'type.googleapis.com/google.protobuf.Any', 'value': { '@type': 'type.googleapis.com/protobuf_unittest.TestAllTypes', 'singleInt32': 20 } } }", + formatter.Format(message)); + } + + [Test] + public void AnyUnknownType() + { + // The default type registry doesn't have any types in it. + var message = new TestAllTypes(); + var any = Any.Pack(message); + Assert.Throws<InvalidOperationException>(() => JsonFormatter.Default.Format(any)); + } + /// <summary> /// Checks that the actual JSON is the same as the expected JSON - but after replacing /// all apostrophes in the expected JSON with double quotes. This basically makes the tests easier diff --git a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs index b3664770..874489e4 100644 --- a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs @@ -30,6 +30,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Reflection; using Google.Protobuf.TestProtos; using Google.Protobuf.WellKnownTypes; using NUnit.Framework; @@ -718,6 +719,55 @@ namespace Google.Protobuf } [Test] + public void Any_RegularMessage() + { + var registry = TypeRegistry.FromMessages(TestAllTypes.Descriptor); + var formatter = new JsonFormatter(new JsonFormatter.Settings(false, TypeRegistry.FromMessages(TestAllTypes.Descriptor))); + var message = new TestAllTypes { SingleInt32 = 10, SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 } }; + var original = Any.Pack(message); + var json = formatter.Format(original); // This is tested in JsonFormatterTest + var parser = new JsonParser(new JsonParser.Settings(10, registry)); + Assert.AreEqual(original, parser.Parse<Any>(json)); + string valueFirstJson = "{ \"singleInt32\": 10, \"singleNestedMessage\": { \"bb\": 20 }, \"@type\": \"type.googleapis.com/protobuf_unittest.TestAllTypes\" }"; + Assert.AreEqual(original, parser.Parse<Any>(valueFirstJson)); + } + + [Test] + public void Any_UnknownType() + { + string json = "{ \"@type\": \"type.googleapis.com/bogus\" }"; + Assert.Throws<InvalidOperationException>(() => Any.Parser.ParseJson(json)); + } + + [Test] + public void Any_WellKnownType() + { + var registry = TypeRegistry.FromMessages(Timestamp.Descriptor); + var formatter = new JsonFormatter(new JsonFormatter.Settings(false, registry)); + var timestamp = new DateTime(1673, 6, 19, 12, 34, 56, DateTimeKind.Utc).ToTimestamp(); + var original = Any.Pack(timestamp); + var json = formatter.Format(original); // This is tested in JsonFormatterTest + var parser = new JsonParser(new JsonParser.Settings(10, registry)); + Assert.AreEqual(original, parser.Parse<Any>(json)); + string valueFirstJson = "{ \"value\": \"1673-06-19T12:34:56Z\", \"@type\": \"type.googleapis.com/google.protobuf.Timestamp\" }"; + Assert.AreEqual(original, parser.Parse<Any>(valueFirstJson)); + } + + [Test] + public void Any_Nested() + { + var registry = TypeRegistry.FromMessages(TestWellKnownTypes.Descriptor, TestAllTypes.Descriptor); + var formatter = new JsonFormatter(new JsonFormatter.Settings(false, registry)); + var parser = new JsonParser(new JsonParser.Settings(10, registry)); + var doubleNestedMessage = new TestAllTypes { SingleInt32 = 20 }; + var nestedMessage = Any.Pack(doubleNestedMessage); + var message = new TestWellKnownTypes { AnyField = Any.Pack(nestedMessage) }; + var json = formatter.Format(message); + // Use the descriptor-based parser just for a change. + Assert.AreEqual(message, parser.Parse(json, TestWellKnownTypes.Descriptor)); + } + + [Test] public void DataAfterObject() { string json = "{} 10"; diff --git a/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs b/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs index a38efeed..a0a62227 100644 --- a/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs @@ -85,7 +85,7 @@ namespace Google.Protobuf public void ObjectDepth() { string json = "{ \"foo\": { \"x\": 1, \"y\": [ 0 ] } }"; - var tokenizer = new JsonTokenizer(new StringReader(json)); + var tokenizer = JsonTokenizer.FromTextReader(new StringReader(json)); // If we had more tests like this, I'd introduce a helper method... but for one test, it's not worth it. Assert.AreEqual(0, tokenizer.ObjectDepth); Assert.AreEqual(JsonToken.StartObject, tokenizer.Next()); @@ -118,7 +118,7 @@ namespace Google.Protobuf public void ObjectDepth_WithPushBack() { string json = "{}"; - var tokenizer = new JsonTokenizer(new StringReader(json)); + var tokenizer = JsonTokenizer.FromTextReader(new StringReader(json)); Assert.AreEqual(0, tokenizer.ObjectDepth); var token = tokenizer.Next(); Assert.AreEqual(1, tokenizer.ObjectDepth); @@ -275,7 +275,7 @@ namespace Google.Protobuf // Note: we don't test that the earlier tokens are exactly as expected, // partly because that's hard to parameterize. var reader = new StringReader(json.Replace('\'', '"')); - var tokenizer = new JsonTokenizer(reader); + var tokenizer = JsonTokenizer.FromTextReader(reader); for (int i = 0; i < expectedValidTokens; i++) { Assert.IsNotNull(tokenizer.Next()); @@ -334,7 +334,7 @@ namespace Google.Protobuf [Test] public void NextAfterEndDocumentThrows() { - var tokenizer = new JsonTokenizer(new StringReader("null")); + var tokenizer = JsonTokenizer.FromTextReader(new StringReader("null")); Assert.AreEqual(JsonToken.Null, tokenizer.Next()); Assert.AreEqual(JsonToken.EndDocument, tokenizer.Next()); Assert.Throws<InvalidOperationException>(() => tokenizer.Next()); @@ -343,7 +343,7 @@ namespace Google.Protobuf [Test] public void CanPushBackEndDocument() { - var tokenizer = new JsonTokenizer(new StringReader("null")); + var tokenizer = JsonTokenizer.FromTextReader(new StringReader("null")); Assert.AreEqual(JsonToken.Null, tokenizer.Next()); Assert.AreEqual(JsonToken.EndDocument, tokenizer.Next()); tokenizer.PushBack(JsonToken.EndDocument); @@ -373,7 +373,7 @@ namespace Google.Protobuf private static void AssertTokensNoReplacement(string json, params JsonToken[] expectedTokens) { var reader = new StringReader(json); - var tokenizer = new JsonTokenizer(reader); + var tokenizer = JsonTokenizer.FromTextReader(reader); for (int i = 0; i < expectedTokens.Length; i++) { var actualToken = tokenizer.Next(); @@ -393,7 +393,7 @@ namespace Google.Protobuf private static void AssertThrowsAfter(string json, params JsonToken[] expectedTokens) { var reader = new StringReader(json); - var tokenizer = new JsonTokenizer(reader); + var tokenizer = JsonTokenizer.FromTextReader(reader); for (int i = 0; i < expectedTokens.Length; i++) { var actualToken = tokenizer.Next(); diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs index 5ff47ed2..3e9999e4 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs @@ -425,7 +425,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -633,7 +633,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -741,7 +741,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -851,7 +851,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1121,7 +1121,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1318,7 +1318,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1427,7 +1427,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs index f257b46c..72ada3de 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs @@ -110,7 +110,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs index 2881ca0f..45f0e247 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs @@ -96,7 +96,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs index cf34e8bc..9ac2d7ac 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs @@ -126,7 +126,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -204,7 +204,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -282,7 +282,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -405,7 +405,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -511,7 +511,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -668,7 +668,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -831,7 +831,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -947,7 +947,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1056,7 +1056,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1279,7 +1279,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs index 04de603b..462ae9f9 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs @@ -927,7 +927,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1600,7 +1600,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1736,7 +1736,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1873,7 +1873,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1980,7 +1980,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2070,7 +2070,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2162,7 +2162,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2291,7 +2291,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2421,7 +2421,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2547,7 +2547,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2669,7 +2669,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2883,7 +2883,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3107,7 +3107,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3278,7 +3278,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3400,7 +3400,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3506,7 +3506,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3608,7 +3608,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3704,7 +3704,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3807,7 +3807,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3913,7 +3913,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4016,7 +4016,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4119,7 +4119,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4222,7 +4222,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4325,7 +4325,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4486,7 +4486,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4780,7 +4780,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5140,7 +5140,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5414,7 +5414,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5554,7 +5554,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5647,7 +5647,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5723,7 +5723,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5799,7 +5799,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5875,7 +5875,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5951,7 +5951,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -6027,7 +6027,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs index 642e5f91..c00b0f41 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs @@ -466,7 +466,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1106,7 +1106,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1625,7 +1625,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2213,7 +2213,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs index 0a2b8b32..f3593e5f 100644 --- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs +++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs @@ -62,5 +62,28 @@ namespace Google.Protobuf.WellKnownTypes var unpacked = any.Unpack<TestAllTypes>(); Assert.AreEqual(message, unpacked); } + + [Test] + public void ToString_WithValues() + { + var message = SampleMessages.CreateFullTestAllTypes(); + var any = Any.Pack(message); + var text = any.ToString(); + Assert.That(text, Is.StringContaining("\"@value\": \"" + message.ToByteString().ToBase64() + "\"")); + } + + [Test] + public void ToString_Empty() + { + var any = new Any(); + Assert.AreEqual("{ \"@type\": \"\", \"@value\": \"\" }", any.ToString()); + } + + [Test] + public void ToString_MessageContainingAny() + { + var message = new TestWellKnownTypes { AnyField = new Any() }; + Assert.AreEqual("{ \"anyField\": { \"@type\": \"\", \"@value\": \"\" } }", message.ToString()); + } } } diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.nuspec b/csharp/src/Google.Protobuf/Google.Protobuf.nuspec index 9542138a..2f691e3c 100644 --- a/csharp/src/Google.Protobuf/Google.Protobuf.nuspec +++ b/csharp/src/Google.Protobuf/Google.Protobuf.nuspec @@ -1,11 +1,11 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <package> <metadata> <id>Google.Protobuf</id> <title>Google Protocol Buffers C#</title> <summary>C# runtime library for Protocol Buffers - Google's data interchange format.</summary> <description>See project site for more info.</description> - <version>3.0.0-alpha4</version> + <version>3.0.0-beta2</version> <authors>Google Inc.</authors> <owners>protobuf-packages</owners> <licenseUrl>https://github.com/google/protobuf/blob/master/LICENSE</licenseUrl> @@ -14,24 +14,43 @@ <releaseNotes>C# proto3 support</releaseNotes> <copyright>Copyright 2015, Google Inc.</copyright> <tags>Protocol Buffers Binary Serialization Format Google proto proto3</tags> + <dependencies> + <group targetFramework="dotnet"> + <dependency id="System.Collections" version="4.0.0" /> + <dependency id="System.Diagnostics.Debug" version="4.0.0" /> + <dependency id="System.Globalization" version="4.0.0" /> + <dependency id="System.IO" version="4.0.0" /> + <dependency id="System.Linq" version="4.0.0" /> + <dependency id="System.Linq.Expressions" version="4.0.0" /> + <dependency id="System.ObjectModel" version="4.0.0" /> + <dependency id="System.Reflection" version="4.0.0" /> + <dependency id="System.Runtime" version="4.0.0" /> + <dependency id="System.Runtime.Extensions" version="4.0.0" /> + <dependency id="System.Text.Encoding" version="4.0.0" /> + <dependency id="System.Text.RegularExpressions" version="4.0.0" /> + </group> + </dependencies> </metadata> <files> <file src="bin/ReleaseSigned/Google.Protobuf.dll" target="lib/portable-net45+netcore45+wpa81+wp8" /> - <file src="bin/ReleaseSigned/Google.Protobuf.pdb" target="lib/portable-net45+netcore45+wpa81+wp8" /> - <file src="bin/ReleaseSigned/Google.Protobuf.xml" target="lib/portable-net45+netcore45+wpa81+wp8" /> - <file src="**\*.cs" target="src" /> - <file src="..\..\..\cmake\Release\protoc.exe" target="tools" /> - <file src="..\..\..\src\google\protobuf\any.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\api.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\descriptor.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\duration.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\empty.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\field_mask.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\source_context.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\struct.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\timestamp.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\any.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\type.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\wrappers.proto" target="tools\google\protobuf" /> + <file src="bin/ReleaseSigned/Google.Protobuf.pdb" target="lib/portable-net45+netcore45+wpa81+wp8" /> + <file src="bin/ReleaseSigned/Google.Protobuf.xml" target="lib/portable-net45+netcore45+wpa81+wp8" /> + <file src="bin/ReleaseSigned/Google.Protobuf.dll" target="lib/dotnet" /> + <file src="bin/ReleaseSigned/Google.Protobuf.pdb" target="lib/dotnet" /> + <file src="bin/ReleaseSigned/Google.Protobuf.xml" target="lib/dotnet" /> + <file src="**\*.cs" target="src" /> + <file src="..\..\..\cmake\Release\protoc.exe" target="tools" /> + <file src="..\..\..\src\google\protobuf\any.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\api.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\descriptor.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\duration.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\empty.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\field_mask.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\source_context.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\struct.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\timestamp.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\any.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\type.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\wrappers.proto" target="tools\google\protobuf" /> </files> -</package> +</package>
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs index 51bb4bf3..7b99f314 100644 --- a/csharp/src/Google.Protobuf/JsonFormatter.cs +++ b/csharp/src/Google.Protobuf/JsonFormatter.cs @@ -55,12 +55,20 @@ namespace Google.Protobuf /// </remarks> public sealed class JsonFormatter { - private static JsonFormatter defaultInstance = new JsonFormatter(Settings.Default); + internal const string AnyTypeUrlField = "@type"; + internal const string AnyDiagnosticValueField = "@value"; + internal const string AnyWellKnownTypeValueField = "value"; + private const string TypeUrlPrefix = "type.googleapis.com"; + private const string NameValueSeparator = ": "; + private const string PropertySeparator = ", "; /// <summary> /// Returns a formatter using the default settings. /// </summary> - public static JsonFormatter Default { get { return defaultInstance; } } + public static JsonFormatter Default { get; } = new JsonFormatter(Settings.Default); + + // A JSON formatter which *only* exists + private static readonly JsonFormatter diagnosticFormatter = new JsonFormatter(Settings.Default); /// <summary> /// The JSON representation of the first 160 characters of Unicode. @@ -130,7 +138,7 @@ namespace Google.Protobuf /// <returns>The formatted message.</returns> public string Format(IMessage message) { - Preconditions.CheckNotNull(message, "message"); + Preconditions.CheckNotNull(message, nameof(message)); StringBuilder builder = new StringBuilder(); if (message.Descriptor.IsWellKnownType) { @@ -143,6 +151,29 @@ namespace Google.Protobuf return builder.ToString(); } + /// <summary> + /// Converts a message to JSON for diagnostic purposes with no extra context. + /// </summary> + /// <remarks> + /// <para> + /// This differs from calling <see cref="Format(IMessage)"/> on the default JSON + /// formatter in its handling of <see cref="Any"/>. As no type registry is available + /// in <see cref="object.ToString"/> calls, the normal way of resolving the type of + /// an <c>Any</c> message cannot be applied. Instead, a JSON property named <c>@value</c> + /// is included with the base64 data from the <see cref="Any.Value"/> property of the message. + /// </para> + /// <para>The value returned by this method is only designed to be used for diagnostic + /// purposes. It may not be parsable by <see cref="JsonParser"/>, and may not be parsable + /// by other Protocol Buffer implementations.</para> + /// </remarks> + /// <param name="message">The message to format for diagnostic purposes.</param> + /// <returns>The diagnostic-only JSON representation of the message</returns> + public static string ToDiagnosticString(IMessage message) + { + Preconditions.CheckNotNull(message, nameof(message)); + return diagnosticFormatter.Format(message); + } + private void WriteMessage(StringBuilder builder, IMessage message) { if (message == null) @@ -151,13 +182,18 @@ namespace Google.Protobuf return; } builder.Append("{ "); + bool writtenFields = WriteMessageFields(builder, message, false); + builder.Append(writtenFields ? " }" : "}"); + } + + private bool WriteMessageFields(StringBuilder builder, IMessage message, bool assumeFirstFieldWritten) + { var fields = message.Descriptor.Fields; - bool first = true; + bool first = !assumeFirstFieldWritten; // First non-oneof fields foreach (var field in fields.InFieldNumberOrder()) { var accessor = field.Accessor; - // Oneofs are written later if (field.ContainingOneof != null && field.ContainingOneof.Accessor.GetCaseFieldDescriptor(message) != field) { continue; @@ -178,14 +214,14 @@ namespace Google.Protobuf // Okay, all tests complete: let's write the field value... if (!first) { - builder.Append(", "); + builder.Append(PropertySeparator); } WriteString(builder, ToCamelCase(accessor.Descriptor.Name)); - builder.Append(": "); + builder.Append(NameValueSeparator); WriteValue(builder, value); first = false; } - builder.Append(first ? "}" : " }"); + return !first; } // Converted from src/google/protobuf/util/internal/utility.cc ToCamelCase @@ -378,6 +414,8 @@ namespace Google.Protobuf /// </summary> private void WriteWellKnownTypeValue(StringBuilder builder, MessageDescriptor descriptor, object value, bool inField) { + // Currently, we can never actually get here, because null values are always handled by the caller. But if we *could*, + // this would do the right thing. if (value == null) { WriteNull(builder); @@ -429,6 +467,11 @@ namespace Google.Protobuf WriteStructFieldValue(builder, (IMessage) value); return; } + if (descriptor.FullName == Any.Descriptor.FullName) + { + WriteAny(builder, (IMessage) value); + return; + } WriteMessage(builder, (IMessage) value); } @@ -496,6 +539,69 @@ namespace Google.Protobuf AppendEscapedString(builder, string.Join(",", paths.Cast<string>().Select(ToCamelCase))); } + private void WriteAny(StringBuilder builder, IMessage value) + { + if (ReferenceEquals(this, diagnosticFormatter)) + { + WriteDiagnosticOnlyAny(builder, value); + return; + } + + string typeUrl = (string) value.Descriptor.Fields[Any.TypeUrlFieldNumber].Accessor.GetValue(value); + ByteString data = (ByteString) value.Descriptor.Fields[Any.ValueFieldNumber].Accessor.GetValue(value); + string typeName = GetTypeName(typeUrl); + MessageDescriptor descriptor = settings.TypeRegistry.Find(typeName); + if (descriptor == null) + { + throw new InvalidOperationException($"Type registry has no descriptor for type name '{typeName}'"); + } + IMessage message = descriptor.Parser.ParseFrom(data); + builder.Append("{ "); + WriteString(builder, AnyTypeUrlField); + builder.Append(NameValueSeparator); + WriteString(builder, typeUrl); + + if (descriptor.IsWellKnownType) + { + builder.Append(PropertySeparator); + WriteString(builder, AnyWellKnownTypeValueField); + builder.Append(NameValueSeparator); + WriteWellKnownTypeValue(builder, descriptor, message, true); + } + else + { + WriteMessageFields(builder, message, true); + } + builder.Append(" }"); + } + + private void WriteDiagnosticOnlyAny(StringBuilder builder, IMessage value) + { + string typeUrl = (string) value.Descriptor.Fields[Any.TypeUrlFieldNumber].Accessor.GetValue(value); + ByteString data = (ByteString) value.Descriptor.Fields[Any.ValueFieldNumber].Accessor.GetValue(value); + builder.Append("{ "); + WriteString(builder, AnyTypeUrlField); + builder.Append(NameValueSeparator); + WriteString(builder, typeUrl); + builder.Append(PropertySeparator); + WriteString(builder, AnyDiagnosticValueField); + builder.Append(NameValueSeparator); + builder.Append('"'); + builder.Append(data.ToBase64()); + builder.Append('"'); + builder.Append(" }"); + } + + internal static string GetTypeName(String typeUrl) + { + string[] parts = typeUrl.Split('/'); + if (parts.Length != 2 || parts[0] != TypeUrlPrefix) + { + throw new InvalidProtocolBufferException($"Invalid type url: {typeUrl}"); + } + return parts[1]; + } + /// <summary> /// Appends a number of nanoseconds to a StringBuilder. Either 0 digits are added (in which /// case no "." is appended), or 3 6 or 9 digits. @@ -537,10 +643,10 @@ namespace Google.Protobuf if (!first) { - builder.Append(", "); + builder.Append(PropertySeparator); } WriteString(builder, key); - builder.Append(": "); + builder.Append(NameValueSeparator); WriteStructFieldValue(builder, value); first = false; } @@ -590,7 +696,7 @@ namespace Google.Protobuf } if (!first) { - builder.Append(", "); + builder.Append(PropertySeparator); } WriteValue(builder, value); first = false; @@ -611,7 +717,7 @@ namespace Google.Protobuf } if (!first) { - builder.Append(", "); + builder.Append(PropertySeparator); } string keyText; if (pair.Key is string) @@ -635,7 +741,7 @@ namespace Google.Protobuf throw new ArgumentException("Unhandled dictionary key type: " + pair.Key.GetType()); } WriteString(builder, keyText); - builder.Append(": "); + builder.Append(NameValueSeparator); WriteValue(builder, pair.Value); first = false; } @@ -750,28 +856,50 @@ namespace Google.Protobuf /// </summary> public sealed class Settings { - private static readonly Settings defaultInstance = new Settings(false); - /// <summary> /// Default settings, as used by <see cref="JsonFormatter.Default"/> /// </summary> - public static Settings Default { get { return defaultInstance; } } + public static Settings Default { get; } - private readonly bool formatDefaultValues; + // Workaround for the Mono compiler complaining about XML comments not being on + // valid language elements. + static Settings() + { + Default = new Settings(false); + } /// <summary> /// Whether fields whose values are the default for the field type (e.g. 0 for integers) /// should be formatted (true) or omitted (false). /// </summary> - public bool FormatDefaultValues { get { return formatDefaultValues; } } + public bool FormatDefaultValues { get; } + + /// <summary> + /// The type registry used to format <see cref="Any"/> messages. + /// </summary> + public TypeRegistry TypeRegistry { get; } + + // TODO: Work out how we're going to scale this to multiple settings. "WithXyz" methods? + + /// <summary> + /// Creates a new <see cref="Settings"/> object with the specified formatting of default values + /// and an empty type registry. + /// </summary> + /// <param name="formatDefaultValues"><c>true</c> if default values (0, empty strings etc) should be formatted; <c>false</c> otherwise.</param> + public Settings(bool formatDefaultValues) : this(formatDefaultValues, TypeRegistry.Empty) + { + } /// <summary> - /// Creates a new <see cref="Settings"/> object with the specified formatting of default values. + /// Creates a new <see cref="Settings"/> object with the specified formatting of default values + /// and type registry. /// </summary> /// <param name="formatDefaultValues"><c>true</c> if default values (0, empty strings etc) should be formatted; <c>false</c> otherwise.</param> - public Settings(bool formatDefaultValues) + /// <param name="typeRegistry">The <see cref="TypeRegistry"/> to use when formatting <see cref="Any"/> messages.</param> + public Settings(bool formatDefaultValues, TypeRegistry typeRegistry) { - this.formatDefaultValues = formatDefaultValues; + FormatDefaultValues = formatDefaultValues; + TypeRegistry = Preconditions.CheckNotNull(typeRegistry, nameof(typeRegistry)); } } } diff --git a/csharp/src/Google.Protobuf/JsonParser.cs b/csharp/src/Google.Protobuf/JsonParser.cs index 2019029b..95f9ad35 100644 --- a/csharp/src/Google.Protobuf/JsonParser.cs +++ b/csharp/src/Google.Protobuf/JsonParser.cs @@ -77,6 +77,7 @@ namespace Google.Protobuf { ListValue.Descriptor.FullName, (parser, message, tokenizer) => parser.MergeRepeatedField(message, message.Descriptor.Fields[ListValue.ValuesFieldNumber], tokenizer) }, { Struct.Descriptor.FullName, (parser, message, tokenizer) => parser.MergeStruct(message, tokenizer) }, + { Any.Descriptor.FullName, (parser, message, tokenizer) => parser.MergeAny(message, tokenizer) }, { FieldMask.Descriptor.FullName, (parser, message, tokenizer) => MergeFieldMask(message, tokenizer.Next()) }, { Int32Value.Descriptor.FullName, MergeWrapperField }, { Int64Value.Descriptor.FullName, MergeWrapperField }, @@ -128,7 +129,7 @@ namespace Google.Protobuf /// <param name="jsonReader">Reader providing the JSON to parse.</param> internal void Merge(IMessage message, TextReader jsonReader) { - var tokenizer = new JsonTokenizer(jsonReader); + var tokenizer = JsonTokenizer.FromTextReader(jsonReader); Merge(message, tokenizer); var lastToken = tokenizer.Next(); if (lastToken != JsonToken.EndDocument) @@ -338,6 +339,7 @@ namespace Google.Protobuf /// <exception cref="InvalidProtocolBufferException">The JSON does not represent a Protocol Buffers message correctly</exception> public T Parse<T>(string json) where T : IMessage, new() { + Preconditions.CheckNotNull(json, nameof(json)); return Parse<T>(new StringReader(json)); } @@ -350,11 +352,42 @@ namespace Google.Protobuf /// <exception cref="InvalidProtocolBufferException">The JSON does not represent a Protocol Buffers message correctly</exception> public T Parse<T>(TextReader jsonReader) where T : IMessage, new() { + Preconditions.CheckNotNull(jsonReader, nameof(jsonReader)); T message = new T(); Merge(message, jsonReader); return message; } + /// <summary> + /// Parses <paramref name="json"/> into a new message. + /// </summary> + /// <param name="json">The JSON to parse.</param> + /// <param name="descriptor">Descriptor of message type to parse.</param> + /// <exception cref="InvalidJsonException">The JSON does not comply with RFC 7159</exception> + /// <exception cref="InvalidProtocolBufferException">The JSON does not represent a Protocol Buffers message correctly</exception> + public IMessage Parse(string json, MessageDescriptor descriptor) + { + Preconditions.CheckNotNull(json, nameof(json)); + Preconditions.CheckNotNull(descriptor, nameof(descriptor)); + return Parse(new StringReader(json), descriptor); + } + + /// <summary> + /// Parses JSON read from <paramref name="jsonReader"/> into a new message. + /// </summary> + /// <param name="jsonReader">Reader providing the JSON to parse.</param> + /// <param name="descriptor">Descriptor of message type to parse.</param> + /// <exception cref="InvalidJsonException">The JSON does not comply with RFC 7159</exception> + /// <exception cref="InvalidProtocolBufferException">The JSON does not represent a Protocol Buffers message correctly</exception> + public IMessage Parse(TextReader jsonReader, MessageDescriptor descriptor) + { + Preconditions.CheckNotNull(jsonReader, nameof(jsonReader)); + Preconditions.CheckNotNull(descriptor, nameof(descriptor)); + IMessage message = descriptor.Parser.CreateTemplate(); + Merge(message, jsonReader); + return message; + } + private void MergeStructValue(IMessage message, JsonTokenizer tokenizer) { var firstToken = tokenizer.Next(); @@ -410,6 +443,83 @@ namespace Google.Protobuf MergeMapField(message, field, tokenizer); } + private void MergeAny(IMessage message, JsonTokenizer tokenizer) + { + // Record the token stream until we see the @type property. At that point, we can take the value, consult + // the type registry for the relevant message, and replay the stream, omitting the @type property. + var tokens = new List<JsonToken>(); + + var token = tokenizer.Next(); + if (token.Type != JsonToken.TokenType.StartObject) + { + throw new InvalidProtocolBufferException("Expected object value for Any"); + } + int typeUrlObjectDepth = tokenizer.ObjectDepth; + + // The check for the property depth protects us from nested Any values which occur before the type URL + // for *this* Any. + while (token.Type != JsonToken.TokenType.Name || + token.StringValue != JsonFormatter.AnyTypeUrlField || + tokenizer.ObjectDepth != typeUrlObjectDepth) + { + tokens.Add(token); + token = tokenizer.Next(); + } + + // Don't add the @type property or its value to the recorded token list + token = tokenizer.Next(); + if (token.Type != JsonToken.TokenType.StringValue) + { + throw new InvalidProtocolBufferException("Expected string value for Any.@type"); + } + string typeUrl = token.StringValue; + string typeName = JsonFormatter.GetTypeName(typeUrl); + + MessageDescriptor descriptor = settings.TypeRegistry.Find(typeName); + if (descriptor == null) + { + throw new InvalidOperationException($"Type registry has no descriptor for type name '{typeName}'"); + } + + // Now replay the token stream we've already read and anything that remains of the object, just parsing it + // as normal. Our original tokenizer should end up at the end of the object. + var replay = JsonTokenizer.FromReplayedTokens(tokens, tokenizer); + var body = descriptor.Parser.CreateTemplate(); + if (descriptor.IsWellKnownType) + { + MergeWellKnownTypeAnyBody(body, replay); + } + else + { + Merge(body, replay); + } + var data = body.ToByteString(); + + // Now that we have the message data, we can pack it into an Any (the message received as a parameter). + message.Descriptor.Fields[Any.TypeUrlFieldNumber].Accessor.SetValue(message, typeUrl); + message.Descriptor.Fields[Any.ValueFieldNumber].Accessor.SetValue(message, data); + } + + // Well-known types end up in a property called "value" in the JSON. As there's no longer a @type property + // in the given JSON token stream, we should *only* have tokens of start-object, name("value"), the value + // itself, and then end-object. + private void MergeWellKnownTypeAnyBody(IMessage body, JsonTokenizer tokenizer) + { + var token = tokenizer.Next(); // Definitely start-object; checked in previous method + token = tokenizer.Next(); + // TODO: What about an absent Int32Value, for example? + if (token.Type != JsonToken.TokenType.Name || token.StringValue != JsonFormatter.AnyWellKnownTypeValueField) + { + throw new InvalidProtocolBufferException($"Expected '{JsonFormatter.AnyWellKnownTypeValueField}' property for well-known type Any body"); + } + Merge(body, tokenizer); + token = tokenizer.Next(); + if (token.Type != JsonToken.TokenType.EndObject) + { + throw new InvalidProtocolBufferException($"Expected end-object token after @type/value for well-known type"); + } + } + #region Utility methods which don't depend on the state (or settings) of the parser. private static object ParseMapKey(FieldDescriptor field, string keyText) { @@ -789,29 +899,48 @@ namespace Google.Protobuf /// </summary> public sealed class Settings { - private static readonly Settings defaultInstance = new Settings(CodedInputStream.DefaultRecursionLimit); - - private readonly int recursionLimit; - /// <summary> - /// Default settings, as used by <see cref="JsonParser.Default"/> + /// Default settings, as used by <see cref="JsonParser.Default"/>. This has the same default + /// recursion limit as <see cref="CodedInputStream"/>, and an empty type registry. /// </summary> - public static Settings Default { get { return defaultInstance; } } + public static Settings Default { get; } + + // Workaround for the Mono compiler complaining about XML comments not being on + // valid language elements. + static Settings() + { + Default = new Settings(CodedInputStream.DefaultRecursionLimit); + } /// <summary> /// The maximum depth of messages to parse. Note that this limit only applies to parsing /// messages, not collections - so a message within a collection within a message only counts as /// depth 2, not 3. /// </summary> - public int RecursionLimit { get { return recursionLimit; } } + public int RecursionLimit { get; } + + /// <summary> + /// The type registry used to parse <see cref="Any"/> messages. + /// </summary> + public TypeRegistry TypeRegistry { get; } /// <summary> /// Creates a new <see cref="Settings"/> object with the specified recursion limit. /// </summary> /// <param name="recursionLimit">The maximum depth of messages to parse</param> - public Settings(int recursionLimit) + public Settings(int recursionLimit) : this(recursionLimit, TypeRegistry.Empty) + { + } + + /// <summary> + /// Creates a new <see cref="Settings"/> object with the specified recursion limit and type registry. + /// </summary> + /// <param name="recursionLimit">The maximum depth of messages to parse</param> + /// <param name="typeRegistry">The type registry used to parse <see cref="Any"/> messages</param> + public Settings(int recursionLimit, TypeRegistry typeRegistry) { - this.recursionLimit = recursionLimit; + RecursionLimit = recursionLimit; + TypeRegistry = Preconditions.CheckNotNull(typeRegistry, nameof(typeRegistry)); } } } diff --git a/csharp/src/Google.Protobuf/JsonTokenizer.cs b/csharp/src/Google.Protobuf/JsonTokenizer.cs index 6589427a..09a6d43b 100644 --- a/csharp/src/Google.Protobuf/JsonTokenizer.cs +++ b/csharp/src/Google.Protobuf/JsonTokenizer.cs @@ -47,32 +47,38 @@ namespace Google.Protobuf /// between values. It validates the token stream as it goes - so callers can assume that the /// tokens it produces are appropriate. For example, it would never produce "start object, end array." /// </para> + /// <para>Implementation details: the base class handles single token push-back and </para> /// <para>Not thread-safe.</para> /// </remarks> - internal sealed class JsonTokenizer + internal abstract class JsonTokenizer { - // The set of states in which a value is valid next token. - private static readonly State ValueStates = State.ArrayStart | State.ArrayAfterComma | State.ObjectAfterColon | State.StartOfDocument; - - private readonly Stack<ContainerType> containerStack = new Stack<ContainerType>(); - private readonly PushBackReader reader; private JsonToken bufferedToken; - private State state; - private int objectDepth = 0; /// <summary> - /// Returns the depth of the stack, purely in objects (not collections). - /// Informally, this is the number of remaining unclosed '{' characters we have. + /// Creates a tokenizer that reads from the given text reader. /// </summary> - internal int ObjectDepth { get { return objectDepth; } } + internal static JsonTokenizer FromTextReader(TextReader reader) + { + return new JsonTextTokenizer(reader); + } - internal JsonTokenizer(TextReader reader) + /// <summary> + /// Creates a tokenizer that first replays the given list of tokens, then continues reading + /// from another tokenizer. Note that if the returned tokenizer is "pushed back", that does not push back + /// on the continuation tokenizer, or vice versa. Care should be taken when using this method - it was + /// created for the sake of Any parsing. + /// </summary> + internal static JsonTokenizer FromReplayedTokens(IList<JsonToken> tokens, JsonTokenizer continuation) { - this.reader = new PushBackReader(reader); - state = State.StartOfDocument; - containerStack.Push(ContainerType.Document); + return new JsonReplayTokenizer(tokens, continuation); } + /// <summary> + /// Returns the depth of the stack, purely in objects (not collections). + /// Informally, this is the number of remaining unclosed '{' characters we have. + /// </summary> + internal int ObjectDepth { get; private set; } + // TODO: Why do we allow a different token to be pushed back? It might be better to always remember the previous // token returned, and allow a parameterless Rewind() method (which could only be called once, just like the current PushBack). internal void PushBack(JsonToken token) @@ -84,11 +90,11 @@ namespace Google.Protobuf bufferedToken = token; if (token.Type == JsonToken.TokenType.StartObject) { - objectDepth--; + ObjectDepth--; } else if (token.Type == JsonToken.TokenType.EndObject) { - objectDepth++; + ObjectDepth++; } } @@ -96,574 +102,636 @@ namespace Google.Protobuf /// Returns the next JSON token in the stream. An EndDocument token is returned to indicate the end of the stream, /// after which point <c>Next()</c> should not be called again. /// </summary> - /// <remarks> - /// This method essentially just loops through characters skipping whitespace, validating and - /// changing state (e.g. from ObjectBeforeColon to ObjectAfterColon) - /// until it reaches something which will be a genuine token (e.g. a start object, or a value) at which point - /// it returns the token. Although the method is large, it would be relatively hard to break down further... most - /// of it is the large switch statement, which sometimes returns and sometimes doesn't. - /// </remarks> + /// <remarks>This implementation provides single-token buffering, and calls <see cref="NextImpl"/> if there is no buffered token.</remarks> /// <returns>The next token in the stream. This is never null.</returns> /// <exception cref="InvalidOperationException">This method is called after an EndDocument token has been returned</exception> /// <exception cref="InvalidJsonException">The input text does not comply with RFC 7159</exception> internal JsonToken Next() { + JsonToken tokenToReturn; if (bufferedToken != null) { - var ret = bufferedToken; + tokenToReturn = bufferedToken; bufferedToken = null; - if (ret.Type == JsonToken.TokenType.StartObject) - { - objectDepth++; - } - else if (ret.Type == JsonToken.TokenType.EndObject) - { - objectDepth--; - } - return ret; } - if (state == State.ReaderExhausted) + else { - throw new InvalidOperationException("Next() called after end of document"); + tokenToReturn = NextImpl(); } - while (true) + if (tokenToReturn.Type == JsonToken.TokenType.StartObject) { - var next = reader.Read(); - if (next == null) - { - ValidateState(State.ExpectedEndOfDocument, "Unexpected end of document in state: "); - state = State.ReaderExhausted; - return JsonToken.EndDocument; - } - switch (next.Value) - { - // Skip whitespace between tokens - case ' ': - case '\t': - case '\r': - case '\n': - break; - case ':': - ValidateState(State.ObjectBeforeColon, "Invalid state to read a colon: "); - state = State.ObjectAfterColon; - break; - case ',': - ValidateState(State.ObjectAfterProperty | State.ArrayAfterValue, "Invalid state to read a colon: "); - state = state == State.ObjectAfterProperty ? State.ObjectAfterComma : State.ArrayAfterComma; - break; - case '"': - string stringValue = ReadString(); - if ((state & (State.ObjectStart | State.ObjectAfterComma)) != 0) - { - state = State.ObjectBeforeColon; - return JsonToken.Name(stringValue); - } - else - { - ValidateAndModifyStateForValue("Invalid state to read a double quote: "); - return JsonToken.Value(stringValue); - } - case '{': - ValidateState(ValueStates, "Invalid state to read an open brace: "); - state = State.ObjectStart; - containerStack.Push(ContainerType.Object); - objectDepth++; - return JsonToken.StartObject; - case '}': - ValidateState(State.ObjectAfterProperty | State.ObjectStart, "Invalid state to read a close brace: "); - PopContainer(); - objectDepth--; - return JsonToken.EndObject; - case '[': - ValidateState(ValueStates, "Invalid state to read an open square bracket: "); - state = State.ArrayStart; - containerStack.Push(ContainerType.Array); - return JsonToken.StartArray; - case ']': - ValidateState(State.ArrayAfterValue | State.ArrayStart, "Invalid state to read a close square bracket: "); - PopContainer(); - return JsonToken.EndArray; - case 'n': // Start of null - ConsumeLiteral("null"); - ValidateAndModifyStateForValue("Invalid state to read a null literal: "); - return JsonToken.Null; - case 't': // Start of true - ConsumeLiteral("true"); - ValidateAndModifyStateForValue("Invalid state to read a true literal: "); - return JsonToken.True; - case 'f': // Start of false - ConsumeLiteral("false"); - ValidateAndModifyStateForValue("Invalid state to read a false literal: "); - return JsonToken.False; - case '-': // Start of a number - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - double number = ReadNumber(next.Value); - ValidateAndModifyStateForValue("Invalid state to read a number token: "); - return JsonToken.Value(number); - default: - throw new InvalidJsonException("Invalid first character of token: " + next.Value); - } + ObjectDepth++; } - } - - private void ValidateState(State validStates, string errorPrefix) - { - if ((validStates & state) == 0) + else if (tokenToReturn.Type == JsonToken.TokenType.EndObject) { - throw reader.CreateException(errorPrefix + state); + ObjectDepth--; } + return tokenToReturn; } /// <summary> - /// Reads a string token. It is assumed that the opening " has already been read. + /// Returns the next JSON token in the stream, when requested by the base class. (The <see cref="Next"/> method delegates + /// to this if it doesn't have a buffered token.) /// </summary> - private string ReadString() - { - var value = new StringBuilder(); - bool haveHighSurrogate = false; - while (true) - { - char c = reader.ReadOrFail("Unexpected end of text while reading string"); - if (c < ' ') - { - throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in string literal: U+{0:x4}", (int) c)); - } - if (c == '"') - { - if (haveHighSurrogate) - { - throw reader.CreateException("Invalid use of surrogate pair code units"); - } - return value.ToString(); - } - if (c == '\\') - { - c = ReadEscapedCharacter(); - } - // TODO: Consider only allowing surrogate pairs that are either both escaped, - // or both not escaped. It would be a very odd text stream that contained a "lone" high surrogate - // followed by an escaped low surrogate or vice versa... and that couldn't even be represented in UTF-8. - if (haveHighSurrogate != char.IsLowSurrogate(c)) - { - throw reader.CreateException("Invalid use of surrogate pair code units"); - } - haveHighSurrogate = char.IsHighSurrogate(c); - value.Append(c); - } - } + /// <exception cref="InvalidOperationException">This method is called after an EndDocument token has been returned</exception> + /// <exception cref="InvalidJsonException">The input text does not comply with RFC 7159</exception> + protected abstract JsonToken NextImpl(); /// <summary> - /// Reads an escaped character. It is assumed that the leading backslash has already been read. + /// Tokenizer which first exhausts a list of tokens, then consults another tokenizer. /// </summary> - private char ReadEscapedCharacter() + private class JsonReplayTokenizer : JsonTokenizer { - char c = reader.ReadOrFail("Unexpected end of text while reading character escape sequence"); - switch (c) + private readonly IList<JsonToken> tokens; + private readonly JsonTokenizer nextTokenizer; + private int nextTokenIndex; + + internal JsonReplayTokenizer(IList<JsonToken> tokens, JsonTokenizer nextTokenizer) { - case 'n': - return '\n'; - case '\\': - return '\\'; - case 'b': - return '\b'; - case 'f': - return '\f'; - case 'r': - return '\r'; - case 't': - return '\t'; - case '"': - return '"'; - case '/': - return '/'; - case 'u': - return ReadUnicodeEscape(); - default: - throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in character escape sequence: U+{0:x4}", (int) c)); + this.tokens = tokens; + this.nextTokenizer = nextTokenizer; } - } - /// <summary> - /// Reads an escaped Unicode 4-nybble hex sequence. It is assumed that the leading \u has already been read. - /// </summary> - private char ReadUnicodeEscape() - { - int result = 0; - for (int i = 0; i < 4; i++) + // FIXME: Object depth not maintained... + protected override JsonToken NextImpl() { - char c = reader.ReadOrFail("Unexpected end of text while reading Unicode escape sequence"); - int nybble; - if (c >= '0' && c <= '9') + if (nextTokenIndex >= tokens.Count) { - nybble = c - '0'; + return nextTokenizer.Next(); } - else if (c >= 'a' && c <= 'f') - { - nybble = c - 'a' + 10; - } - else if (c >= 'A' && c <= 'F') - { - nybble = c - 'A' + 10; - } - else - { - throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in character escape sequence: U+{0:x4}", (int) c)); - } - result = (result << 4) + nybble; + return tokens[nextTokenIndex++]; } - return (char) result; } /// <summary> - /// Consumes a text-only literal, throwing an exception if the read text doesn't match it. - /// It is assumed that the first letter of the literal has already been read. + /// Tokenizer which does all the *real* work of parsing JSON. /// </summary> - private void ConsumeLiteral(string text) + private sealed class JsonTextTokenizer : JsonTokenizer { - for (int i = 1; i < text.Length; i++) + // The set of states in which a value is valid next token. + private static readonly State ValueStates = State.ArrayStart | State.ArrayAfterComma | State.ObjectAfterColon | State.StartOfDocument; + + private readonly Stack<ContainerType> containerStack = new Stack<ContainerType>(); + private readonly PushBackReader reader; + private State state; + + internal JsonTextTokenizer(TextReader reader) { - char? next = reader.Read(); - if (next == null) + this.reader = new PushBackReader(reader); + state = State.StartOfDocument; + containerStack.Push(ContainerType.Document); + } + + /// <remarks> + /// This method essentially just loops through characters skipping whitespace, validating and + /// changing state (e.g. from ObjectBeforeColon to ObjectAfterColon) + /// until it reaches something which will be a genuine token (e.g. a start object, or a value) at which point + /// it returns the token. Although the method is large, it would be relatively hard to break down further... most + /// of it is the large switch statement, which sometimes returns and sometimes doesn't. + /// </remarks> + protected override JsonToken NextImpl() + { + if (state == State.ReaderExhausted) { - throw reader.CreateException("Unexpected end of text while reading literal token " + text); + throw new InvalidOperationException("Next() called after end of document"); } - if (next.Value != text[i]) + while (true) { - throw reader.CreateException("Unexpected character while reading literal token " + text); + var next = reader.Read(); + if (next == null) + { + ValidateState(State.ExpectedEndOfDocument, "Unexpected end of document in state: "); + state = State.ReaderExhausted; + return JsonToken.EndDocument; + } + switch (next.Value) + { + // Skip whitespace between tokens + case ' ': + case '\t': + case '\r': + case '\n': + break; + case ':': + ValidateState(State.ObjectBeforeColon, "Invalid state to read a colon: "); + state = State.ObjectAfterColon; + break; + case ',': + ValidateState(State.ObjectAfterProperty | State.ArrayAfterValue, "Invalid state to read a colon: "); + state = state == State.ObjectAfterProperty ? State.ObjectAfterComma : State.ArrayAfterComma; + break; + case '"': + string stringValue = ReadString(); + if ((state & (State.ObjectStart | State.ObjectAfterComma)) != 0) + { + state = State.ObjectBeforeColon; + return JsonToken.Name(stringValue); + } + else + { + ValidateAndModifyStateForValue("Invalid state to read a double quote: "); + return JsonToken.Value(stringValue); + } + case '{': + ValidateState(ValueStates, "Invalid state to read an open brace: "); + state = State.ObjectStart; + containerStack.Push(ContainerType.Object); + return JsonToken.StartObject; + case '}': + ValidateState(State.ObjectAfterProperty | State.ObjectStart, "Invalid state to read a close brace: "); + PopContainer(); + return JsonToken.EndObject; + case '[': + ValidateState(ValueStates, "Invalid state to read an open square bracket: "); + state = State.ArrayStart; + containerStack.Push(ContainerType.Array); + return JsonToken.StartArray; + case ']': + ValidateState(State.ArrayAfterValue | State.ArrayStart, "Invalid state to read a close square bracket: "); + PopContainer(); + return JsonToken.EndArray; + case 'n': // Start of null + ConsumeLiteral("null"); + ValidateAndModifyStateForValue("Invalid state to read a null literal: "); + return JsonToken.Null; + case 't': // Start of true + ConsumeLiteral("true"); + ValidateAndModifyStateForValue("Invalid state to read a true literal: "); + return JsonToken.True; + case 'f': // Start of false + ConsumeLiteral("false"); + ValidateAndModifyStateForValue("Invalid state to read a false literal: "); + return JsonToken.False; + case '-': // Start of a number + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + double number = ReadNumber(next.Value); + ValidateAndModifyStateForValue("Invalid state to read a number token: "); + return JsonToken.Value(number); + default: + throw new InvalidJsonException("Invalid first character of token: " + next.Value); + } } } - } - private double ReadNumber(char initialCharacter) - { - StringBuilder builder = new StringBuilder(); - if (initialCharacter == '-') - { - builder.Append("-"); - } - else - { - reader.PushBack(initialCharacter); - } - // Each method returns the character it read that doesn't belong in that part, - // so we know what to do next, including pushing the character back at the end. - // null is returned for "end of text". - char? next = ReadInt(builder); - if (next == '.') + private void ValidateState(State validStates, string errorPrefix) { - next = ReadFrac(builder); - } - if (next == 'e' || next == 'E') - { - next = ReadExp(builder); - } - // If we read a character which wasn't part of the number, push it back so we can read it again - // to parse the next token. - if (next != null) - { - reader.PushBack(next.Value); + if ((validStates & state) == 0) + { + throw reader.CreateException(errorPrefix + state); + } } - // TODO: What exception should we throw if the value can't be represented as a double? - try - { - return double.Parse(builder.ToString(), - NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent, - CultureInfo.InvariantCulture); - } - catch (OverflowException) + /// <summary> + /// Reads a string token. It is assumed that the opening " has already been read. + /// </summary> + private string ReadString() { - throw reader.CreateException("Numeric value out of range: " + builder); + var value = new StringBuilder(); + bool haveHighSurrogate = false; + while (true) + { + char c = reader.ReadOrFail("Unexpected end of text while reading string"); + if (c < ' ') + { + throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in string literal: U+{0:x4}", (int) c)); + } + if (c == '"') + { + if (haveHighSurrogate) + { + throw reader.CreateException("Invalid use of surrogate pair code units"); + } + return value.ToString(); + } + if (c == '\\') + { + c = ReadEscapedCharacter(); + } + // TODO: Consider only allowing surrogate pairs that are either both escaped, + // or both not escaped. It would be a very odd text stream that contained a "lone" high surrogate + // followed by an escaped low surrogate or vice versa... and that couldn't even be represented in UTF-8. + if (haveHighSurrogate != char.IsLowSurrogate(c)) + { + throw reader.CreateException("Invalid use of surrogate pair code units"); + } + haveHighSurrogate = char.IsHighSurrogate(c); + value.Append(c); + } } - } - private char? ReadInt(StringBuilder builder) - { - char first = reader.ReadOrFail("Invalid numeric literal"); - if (first < '0' || first > '9') - { - throw reader.CreateException("Invalid numeric literal"); - } - builder.Append(first); - int digitCount; - char? next = ConsumeDigits(builder, out digitCount); - if (first == '0' && digitCount != 0) + /// <summary> + /// Reads an escaped character. It is assumed that the leading backslash has already been read. + /// </summary> + private char ReadEscapedCharacter() { - throw reader.CreateException("Invalid numeric literal: leading 0 for non-zero value."); + char c = reader.ReadOrFail("Unexpected end of text while reading character escape sequence"); + switch (c) + { + case 'n': + return '\n'; + case '\\': + return '\\'; + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'r': + return '\r'; + case 't': + return '\t'; + case '"': + return '"'; + case '/': + return '/'; + case 'u': + return ReadUnicodeEscape(); + default: + throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in character escape sequence: U+{0:x4}", (int) c)); + } } - return next; - } - private char? ReadFrac(StringBuilder builder) - { - builder.Append('.'); // Already consumed this - int digitCount; - char? next = ConsumeDigits(builder, out digitCount); - if (digitCount == 0) + /// <summary> + /// Reads an escaped Unicode 4-nybble hex sequence. It is assumed that the leading \u has already been read. + /// </summary> + private char ReadUnicodeEscape() { - throw reader.CreateException("Invalid numeric literal: fraction with no trailing digits"); + int result = 0; + for (int i = 0; i < 4; i++) + { + char c = reader.ReadOrFail("Unexpected end of text while reading Unicode escape sequence"); + int nybble; + if (c >= '0' && c <= '9') + { + nybble = c - '0'; + } + else if (c >= 'a' && c <= 'f') + { + nybble = c - 'a' + 10; + } + else if (c >= 'A' && c <= 'F') + { + nybble = c - 'A' + 10; + } + else + { + throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in character escape sequence: U+{0:x4}", (int) c)); + } + result = (result << 4) + nybble; + } + return (char) result; } - return next; - } - private char? ReadExp(StringBuilder builder) - { - builder.Append('E'); // Already consumed this (or 'e') - char? next = reader.Read(); - if (next == null) + /// <summary> + /// Consumes a text-only literal, throwing an exception if the read text doesn't match it. + /// It is assumed that the first letter of the literal has already been read. + /// </summary> + private void ConsumeLiteral(string text) { - throw reader.CreateException("Invalid numeric literal: exponent with no trailing digits"); + for (int i = 1; i < text.Length; i++) + { + char? next = reader.Read(); + if (next == null) + { + throw reader.CreateException("Unexpected end of text while reading literal token " + text); + } + if (next.Value != text[i]) + { + throw reader.CreateException("Unexpected character while reading literal token " + text); + } + } } - if (next == '-' || next == '+') + + private double ReadNumber(char initialCharacter) { - builder.Append(next.Value); + StringBuilder builder = new StringBuilder(); + if (initialCharacter == '-') + { + builder.Append("-"); + } + else + { + reader.PushBack(initialCharacter); + } + // Each method returns the character it read that doesn't belong in that part, + // so we know what to do next, including pushing the character back at the end. + // null is returned for "end of text". + char? next = ReadInt(builder); + if (next == '.') + { + next = ReadFrac(builder); + } + if (next == 'e' || next == 'E') + { + next = ReadExp(builder); + } + // If we read a character which wasn't part of the number, push it back so we can read it again + // to parse the next token. + if (next != null) + { + reader.PushBack(next.Value); + } + + // TODO: What exception should we throw if the value can't be represented as a double? + try + { + return double.Parse(builder.ToString(), + NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent, + CultureInfo.InvariantCulture); + } + catch (OverflowException) + { + throw reader.CreateException("Numeric value out of range: " + builder); + } } - else + + private char? ReadInt(StringBuilder builder) { - reader.PushBack(next.Value); + char first = reader.ReadOrFail("Invalid numeric literal"); + if (first < '0' || first > '9') + { + throw reader.CreateException("Invalid numeric literal"); + } + builder.Append(first); + int digitCount; + char? next = ConsumeDigits(builder, out digitCount); + if (first == '0' && digitCount != 0) + { + throw reader.CreateException("Invalid numeric literal: leading 0 for non-zero value."); + } + return next; } - int digitCount; - next = ConsumeDigits(builder, out digitCount); - if (digitCount == 0) + + private char? ReadFrac(StringBuilder builder) { - throw reader.CreateException("Invalid numeric literal: exponent without value"); + builder.Append('.'); // Already consumed this + int digitCount; + char? next = ConsumeDigits(builder, out digitCount); + if (digitCount == 0) + { + throw reader.CreateException("Invalid numeric literal: fraction with no trailing digits"); + } + return next; } - return next; - } - private char? ConsumeDigits(StringBuilder builder, out int count) - { - count = 0; - while (true) + private char? ReadExp(StringBuilder builder) { + builder.Append('E'); // Already consumed this (or 'e') char? next = reader.Read(); - if (next == null || next.Value < '0' || next.Value > '9') + if (next == null) + { + throw reader.CreateException("Invalid numeric literal: exponent with no trailing digits"); + } + if (next == '-' || next == '+') { - return next; + builder.Append(next.Value); } - count++; - builder.Append(next.Value); + else + { + reader.PushBack(next.Value); + } + int digitCount; + next = ConsumeDigits(builder, out digitCount); + if (digitCount == 0) + { + throw reader.CreateException("Invalid numeric literal: exponent without value"); + } + return next; } - } - /// <summary> - /// Validates that we're in a valid state to read a value (using the given error prefix if necessary) - /// and changes the state to the appropriate one, e.g. ObjectAfterColon to ObjectAfterProperty. - /// </summary> - private void ValidateAndModifyStateForValue(string errorPrefix) - { - ValidateState(ValueStates, errorPrefix); - switch (state) + private char? ConsumeDigits(StringBuilder builder, out int count) { - case State.StartOfDocument: - state = State.ExpectedEndOfDocument; - return; - case State.ObjectAfterColon: - state = State.ObjectAfterProperty; - return; - case State.ArrayStart: - case State.ArrayAfterComma: - state = State.ArrayAfterValue; - return; - default: - throw new InvalidOperationException("ValidateAndModifyStateForValue does not handle all value states (and should)"); + count = 0; + while (true) + { + char? next = reader.Read(); + if (next == null || next.Value < '0' || next.Value > '9') + { + return next; + } + count++; + builder.Append(next.Value); + } } - } - /// <summary> - /// Pops the top-most container, and sets the state to the appropriate one for the end of a value - /// in the parent container. - /// </summary> - private void PopContainer() - { - containerStack.Pop(); - var parent = containerStack.Peek(); - switch (parent) + /// <summary> + /// Validates that we're in a valid state to read a value (using the given error prefix if necessary) + /// and changes the state to the appropriate one, e.g. ObjectAfterColon to ObjectAfterProperty. + /// </summary> + private void ValidateAndModifyStateForValue(string errorPrefix) { - case ContainerType.Object: - state = State.ObjectAfterProperty; - break; - case ContainerType.Array: - state = State.ArrayAfterValue; - break; - case ContainerType.Document: - state = State.ExpectedEndOfDocument; - break; - default: - throw new InvalidOperationException("Unexpected container type: " + parent); + ValidateState(ValueStates, errorPrefix); + switch (state) + { + case State.StartOfDocument: + state = State.ExpectedEndOfDocument; + return; + case State.ObjectAfterColon: + state = State.ObjectAfterProperty; + return; + case State.ArrayStart: + case State.ArrayAfterComma: + state = State.ArrayAfterValue; + return; + default: + throw new InvalidOperationException("ValidateAndModifyStateForValue does not handle all value states (and should)"); + } } - } - private enum ContainerType - { - Document, Object, Array - } - - /// <summary> - /// Possible states of the tokenizer. - /// </summary> - /// <remarks> - /// <para>This is a flags enum purely so we can simply and efficiently represent a set of valid states - /// for checking.</para> - /// <para> - /// Each is documented with an example, - /// where ^ represents the current position within the text stream. The examples all use string values, - /// but could be any value, including nested objects/arrays. - /// The complete state of the tokenizer also includes a stack to indicate the contexts (arrays/objects). - /// Any additional notional state of "AfterValue" indicates that a value has been completed, at which - /// point there's an immediate transition to ExpectedEndOfDocument, ObjectAfterProperty or ArrayAfterValue. - /// </para> - /// <para> - /// These states were derived manually by reading RFC 7159 carefully. - /// </para> - /// </remarks> - [Flags] - private enum State - { - /// <summary> - /// ^ { "foo": "bar" } - /// Before the value in a document. Next states: ObjectStart, ArrayStart, "AfterValue" - /// </summary> - StartOfDocument = 1 << 0, - /// <summary> - /// { "foo": "bar" } ^ - /// After the value in a document. Next states: ReaderExhausted - /// </summary> - ExpectedEndOfDocument = 1 << 1, - /// <summary> - /// { "foo": "bar" } ^ (and already read to the end of the reader) - /// Terminal state. - /// </summary> - ReaderExhausted = 1 << 2, - /// <summary> - /// { ^ "foo": "bar" } - /// Before the *first* property in an object. - /// Next states: - /// "AfterValue" (empty object) - /// ObjectBeforeColon (read a name) - /// </summary> - ObjectStart = 1 << 3, - /// <summary> - /// { "foo" ^ : "bar", "x": "y" } - /// Next state: ObjectAfterColon - /// </summary> - ObjectBeforeColon = 1 << 4, - /// <summary> - /// { "foo" : ^ "bar", "x": "y" } - /// Before any property other than the first in an object. - /// (Equivalently: after any property in an object) - /// Next states: - /// "AfterValue" (value is simple) - /// ObjectStart (value is object) - /// ArrayStart (value is array) - /// </summary> - ObjectAfterColon = 1 << 5, - /// <summary> - /// { "foo" : "bar" ^ , "x" : "y" } - /// At the end of a property, so expecting either a comma or end-of-object - /// Next states: ObjectAfterComma or "AfterValue" - /// </summary> - ObjectAfterProperty = 1 << 6, - /// <summary> - /// { "foo":"bar", ^ "x":"y" } - /// Read the comma after the previous property, so expecting another property. - /// This is like ObjectStart, but closing brace isn't valid here - /// Next state: ObjectBeforeColon. - /// </summary> - ObjectAfterComma = 1 << 7, - /// <summary> - /// [ ^ "foo", "bar" ] - /// Before the *first* value in an array. - /// Next states: - /// "AfterValue" (read a value) - /// "AfterValue" (end of array; will pop stack) - /// </summary> - ArrayStart = 1 << 8, - /// <summary> - /// [ "foo" ^ , "bar" ] - /// After any value in an array, so expecting either a comma or end-of-array - /// Next states: ArrayAfterComma or "AfterValue" - /// </summary> - ArrayAfterValue = 1 << 9, /// <summary> - /// [ "foo", ^ "bar" ] - /// After a comma in an array, so there *must* be another value (simple or complex). - /// Next states: "AfterValue" (simple value), StartObject, StartArray + /// Pops the top-most container, and sets the state to the appropriate one for the end of a value + /// in the parent container. /// </summary> - ArrayAfterComma = 1 << 10 - } - - /// <summary> - /// Wrapper around a text reader allowing small amounts of buffering and location handling. - /// </summary> - private class PushBackReader - { - // TODO: Add locations for errors etc. - - private readonly TextReader reader; + private void PopContainer() + { + containerStack.Pop(); + var parent = containerStack.Peek(); + switch (parent) + { + case ContainerType.Object: + state = State.ObjectAfterProperty; + break; + case ContainerType.Array: + state = State.ArrayAfterValue; + break; + case ContainerType.Document: + state = State.ExpectedEndOfDocument; + break; + default: + throw new InvalidOperationException("Unexpected container type: " + parent); + } + } - internal PushBackReader(TextReader reader) + private enum ContainerType { - // TODO: Wrap the reader in a BufferedReader? - this.reader = reader; + Document, Object, Array } /// <summary> - /// The buffered next character, if we have one. + /// Possible states of the tokenizer. /// </summary> - private char? nextChar; + /// <remarks> + /// <para>This is a flags enum purely so we can simply and efficiently represent a set of valid states + /// for checking.</para> + /// <para> + /// Each is documented with an example, + /// where ^ represents the current position within the text stream. The examples all use string values, + /// but could be any value, including nested objects/arrays. + /// The complete state of the tokenizer also includes a stack to indicate the contexts (arrays/objects). + /// Any additional notional state of "AfterValue" indicates that a value has been completed, at which + /// point there's an immediate transition to ExpectedEndOfDocument, ObjectAfterProperty or ArrayAfterValue. + /// </para> + /// <para> + /// These states were derived manually by reading RFC 7159 carefully. + /// </para> + /// </remarks> + [Flags] + private enum State + { + /// <summary> + /// ^ { "foo": "bar" } + /// Before the value in a document. Next states: ObjectStart, ArrayStart, "AfterValue" + /// </summary> + StartOfDocument = 1 << 0, + /// <summary> + /// { "foo": "bar" } ^ + /// After the value in a document. Next states: ReaderExhausted + /// </summary> + ExpectedEndOfDocument = 1 << 1, + /// <summary> + /// { "foo": "bar" } ^ (and already read to the end of the reader) + /// Terminal state. + /// </summary> + ReaderExhausted = 1 << 2, + /// <summary> + /// { ^ "foo": "bar" } + /// Before the *first* property in an object. + /// Next states: + /// "AfterValue" (empty object) + /// ObjectBeforeColon (read a name) + /// </summary> + ObjectStart = 1 << 3, + /// <summary> + /// { "foo" ^ : "bar", "x": "y" } + /// Next state: ObjectAfterColon + /// </summary> + ObjectBeforeColon = 1 << 4, + /// <summary> + /// { "foo" : ^ "bar", "x": "y" } + /// Before any property other than the first in an object. + /// (Equivalently: after any property in an object) + /// Next states: + /// "AfterValue" (value is simple) + /// ObjectStart (value is object) + /// ArrayStart (value is array) + /// </summary> + ObjectAfterColon = 1 << 5, + /// <summary> + /// { "foo" : "bar" ^ , "x" : "y" } + /// At the end of a property, so expecting either a comma or end-of-object + /// Next states: ObjectAfterComma or "AfterValue" + /// </summary> + ObjectAfterProperty = 1 << 6, + /// <summary> + /// { "foo":"bar", ^ "x":"y" } + /// Read the comma after the previous property, so expecting another property. + /// This is like ObjectStart, but closing brace isn't valid here + /// Next state: ObjectBeforeColon. + /// </summary> + ObjectAfterComma = 1 << 7, + /// <summary> + /// [ ^ "foo", "bar" ] + /// Before the *first* value in an array. + /// Next states: + /// "AfterValue" (read a value) + /// "AfterValue" (end of array; will pop stack) + /// </summary> + ArrayStart = 1 << 8, + /// <summary> + /// [ "foo" ^ , "bar" ] + /// After any value in an array, so expecting either a comma or end-of-array + /// Next states: ArrayAfterComma or "AfterValue" + /// </summary> + ArrayAfterValue = 1 << 9, + /// <summary> + /// [ "foo", ^ "bar" ] + /// After a comma in an array, so there *must* be another value (simple or complex). + /// Next states: "AfterValue" (simple value), StartObject, StartArray + /// </summary> + ArrayAfterComma = 1 << 10 + } /// <summary> - /// Returns the next character in the stream, or null if we have reached the end. + /// Wrapper around a text reader allowing small amounts of buffering and location handling. /// </summary> - /// <returns></returns> - internal char? Read() + private class PushBackReader { - if (nextChar != null) + // TODO: Add locations for errors etc. + + private readonly TextReader reader; + + internal PushBackReader(TextReader reader) { - char? tmp = nextChar; - nextChar = null; - return tmp; + // TODO: Wrap the reader in a BufferedReader? + this.reader = reader; } - int next = reader.Read(); - return next == -1 ? null : (char?) next; - } - internal char ReadOrFail(string messageOnFailure) - { - char? next = Read(); - if (next == null) + /// <summary> + /// The buffered next character, if we have one. + /// </summary> + private char? nextChar; + + /// <summary> + /// Returns the next character in the stream, or null if we have reached the end. + /// </summary> + /// <returns></returns> + internal char? Read() { - throw CreateException(messageOnFailure); + if (nextChar != null) + { + char? tmp = nextChar; + nextChar = null; + return tmp; + } + int next = reader.Read(); + return next == -1 ? null : (char?) next; } - return next.Value; - } - internal void PushBack(char c) - { - if (nextChar != null) + internal char ReadOrFail(string messageOnFailure) { - throw new InvalidOperationException("Cannot push back when already buffering a character"); + char? next = Read(); + if (next == null) + { + throw CreateException(messageOnFailure); + } + return next.Value; } - nextChar = c; - } - /// <summary> - /// Creates a new exception appropriate for the current state of the reader. - /// </summary> - internal InvalidJsonException CreateException(string message) - { - // TODO: Keep track of and use the location. - return new InvalidJsonException(message); + internal void PushBack(char c) + { + if (nextChar != null) + { + throw new InvalidOperationException("Cannot push back when already buffering a character"); + } + nextChar = c; + } + + /// <summary> + /// Creates a new exception appropriate for the current state of the reader. + /// </summary> + internal InvalidJsonException CreateException(string message) + { + // TODO: Keep track of and use the location. + return new InvalidJsonException(message); + } } } } diff --git a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs index 03685322..d29424ad 100644 --- a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs @@ -225,7 +225,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -489,7 +489,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -827,7 +827,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1021,7 +1021,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1162,7 +1162,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1436,7 +1436,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1741,7 +1741,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1872,7 +1872,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2031,7 +2031,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2196,7 +2196,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2404,7 +2404,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2863,7 +2863,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3302,7 +3302,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3596,7 +3596,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3845,7 +3845,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3990,7 +3990,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4121,7 +4121,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4252,7 +4252,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4451,7 +4451,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4653,7 +4653,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4823,7 +4823,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5051,7 +5051,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs index 0b830b66..efa60a68 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs @@ -165,7 +165,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs index e9330e69..1b925b9c 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs @@ -230,7 +230,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -503,7 +503,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -783,7 +783,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs index 42fda452..4eeff4f0 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs @@ -164,7 +164,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs index 92bc0397..d568a811 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs @@ -94,7 +94,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs index 963b72be..0cd5952a 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs @@ -221,7 +221,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs index d5385642..2972b346 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs @@ -105,7 +105,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs index 73e3cae2..a811ea8b 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs @@ -136,7 +136,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -361,7 +361,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -555,7 +555,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs index 499b0950..adee4bb4 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs @@ -175,7 +175,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs index ef368bd3..a76d02b4 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs @@ -230,7 +230,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -522,7 +522,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -910,7 +910,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1098,7 +1098,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1244,7 +1244,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs index a70b2fb0..43148772 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs @@ -117,7 +117,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -228,7 +228,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -339,7 +339,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -450,7 +450,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -561,7 +561,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -672,7 +672,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -783,7 +783,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -894,7 +894,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1005,7 +1005,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/examples/addressbook.proto b/examples/addressbook.proto index bfdceeaf..23cc2f97 100644 --- a/examples/addressbook.proto +++ b/examples/addressbook.proto @@ -1,16 +1,29 @@ // See README.txt for information and build instructions. - +// +// Note: START and END tags are used in comments to define sections used in +// tutorials. They are not part of the syntax for Protocol Buffers. +// +// To get an in-depth walkthrough of this file and the related examples, see: +// https://developers.google.com/protocol-buffers/docs/tutorials + +// [START declaration] syntax = "proto3"; - package tutorial; +// [END declaration] +// [START java_declaration] option java_package = "com.example.tutorial"; option java_outer_classname = "AddressBookProtos"; +// [END java_declaration] + +// [START csharp_declaration] option csharp_namespace = "Google.Protobuf.Examples.AddressBook"; +// [END csharp_declaration] +// [START messages] message Person { string name = 1; - int32 id = 2; // Unique ID number for this person. + int32 id = 2; // Unique ID number for this person. string email = 3; enum PhoneType { @@ -31,3 +44,4 @@ message Person { message AddressBook { repeated Person people = 1; } +// [END messages] diff --git a/gmock.BUILD b/gmock.BUILD index 66cddea9..82abf275 100644 --- a/gmock.BUILD +++ b/gmock.BUILD @@ -4,6 +4,11 @@ cc_library( "gmock-1.7.0/gtest/src/gtest-all.cc", "gmock-1.7.0/src/gmock-all.cc", ], + hdrs = glob([ + "gmock-1.7.0/**/*.h", + "gmock-1.7.0/gtest/src/*.cc", + "gmock-1.7.0/src/*.cc", + ]), includes = [ "gmock-1.7.0", "gmock-1.7.0/gtest", diff --git a/objectivec/DevTools/full_mac_build.sh b/objectivec/DevTools/full_mac_build.sh index 251f2599..709aae0a 100755 --- a/objectivec/DevTools/full_mac_build.sh +++ b/objectivec/DevTools/full_mac_build.sh @@ -136,7 +136,9 @@ fi if [[ "${DO_AUTOGEN}" == "yes" ]] ; then header "Running autogen & configure" ./autogen.sh - ./configure CXXFLAGS="-mmacosx-version-min=10.9 -Wnon-virtual-dtor -Woverloaded-virtual -Wunused-const-variable -Wunused-function" + ./configure \ + CPPFLAGS="-mmacosx-version-min=10.9 -Wunused-const-variable -Wunused-function" \ + CXXFLAGS="-Wnon-virtual-dtor -Woverloaded-virtual" fi if [[ "${DO_CLEAN}" == "yes" ]] ; then @@ -229,13 +231,8 @@ if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then IOS_SIMULATOR_NAME="Simulator" case "${XCODE_VERSION}" in 6.* ) - XCODEBUILD_TEST_BASE_IOS+=( - -destination "platform=iOS Simulator,name=iPhone 4s,OS=7.1" # 32bit - -destination "platform=iOS Simulator,name=iPhone 6,OS=8.4" # 64bit - -destination "platform=iOS Simulator,name=iPad 2,OS=7.1" # 32bit - -destination "platform=iOS Simulator,name=iPad Air,OS=8.4" # 64bit - ) - IOS_SIMULATOR_NAME="iOS Simulator" + echo "ERROR: Xcode 6.3/6.4 no longer supported for building, please use 7.0 or higher." 1>&2 + exit 10 ;; 7.* ) XCODEBUILD_TEST_BASE_IOS+=( diff --git a/objectivec/GPBDictionary.m b/objectivec/GPBDictionary.m index 31ee410e..6baa2a18 100644 --- a/objectivec/GPBDictionary.m +++ b/objectivec/GPBDictionary.m @@ -45,6 +45,18 @@ // directly. // ------------------------------------------------------------------ +// Used to include code only visible to specific versions of the static +// analyzer. Useful for wrapping code that only exists to silence the analyzer. +// Determine the values you want to use for BEGIN_APPLE_BUILD_VERSION, +// END_APPLE_BUILD_VERSION using: +// xcrun clang -dM -E -x c /dev/null | grep __apple_build_version__ +// Example usage: +// #if GPB_STATIC_ANALYZER_ONLY(5621, 5623) ... #endif +#define GPB_STATIC_ANALYZER_ONLY(BEGIN_APPLE_BUILD_VERSION, END_APPLE_BUILD_VERSION) \ + (defined(__clang_analyzer__) && \ + (__apple_build_version__ >= BEGIN_APPLE_BUILD_VERSION && \ + __apple_build_version__ <= END_APPLE_BUILD_VERSION)) + enum { kMapKeyFieldNumber = 1, kMapValueFieldNumber = 2, @@ -496,6 +508,19 @@ void GPBDictionaryReadEntry(id mapDictionary, } if ((keyDataType == GPBDataTypeString) && GPBDataTypeIsObject(valueDataType)) { +#if GPB_STATIC_ANALYZER_ONLY(6020053, 7000181) + // Limited to Xcode 6.4 - 7.2, are known to fail here. The upper end can + // be raised as needed for new Xcodes. + // + // This is only needed on a "shallow" analyze; on a "deep" analyze, the + // existing code path gets this correct. In shallow, the analyzer decides + // GPBDataTypeIsObject(valueDataType) is both false and true on a single + // path through this function, allowing nil to be used for the + // setObject:forKey:. + if (value.valueString == nil) { + value.valueString = [@"" retain]; + } +#endif // mapDictionary is an NSMutableDictionary [(NSMutableDictionary *)mapDictionary setObject:value.valueString forKey:key.valueString]; @@ -601,7 +626,7 @@ void GPBDictionaryReadEntry(id mapDictionary, //% _dictionary = [[NSMutableDictionary alloc] init]; //% if (count && VNAME##s && keys) { //% for (NSUInteger i = 0; i < count; ++i) { -//% [_dictionary setObject:WRAPPED##VHELPER(VNAME##s[i]) forKey:WRAPPED##KHELPER(keys[i])]; +//%DICTIONARY_VALIDATE_VALUE_##VHELPER(VNAME##s[i], ______)##DICTIONARY_VALIDATE_KEY_##KHELPER(keys[i], ______) [_dictionary setObject:WRAPPED##VHELPER(VNAME##s[i]) forKey:WRAPPED##KHELPER(keys[i])]; //% } //% } //% } @@ -711,7 +736,7 @@ void GPBDictionaryReadEntry(id mapDictionary, //% _validationFunc = (func != NULL ? func : DictDefault_IsValidValue); //% if (count && rawValues && keys) { //% for (NSUInteger i = 0; i < count; ++i) { -//% [_dictionary setObject:WRAPPED##VHELPER(rawValues[i]) forKey:WRAPPED##KHELPER(keys[i])]; +//%DICTIONARY_VALIDATE_KEY_##KHELPER(keys[i], ______) [_dictionary setObject:WRAPPED##VHELPER(rawValues[i]) forKey:WRAPPED##KHELPER(keys[i])]; //% } //% } //% } @@ -776,7 +801,7 @@ void GPBDictionaryReadEntry(id mapDictionary, //%DICTIONARY_MUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, value, Raw) //% //%- (void)setValue:(VALUE_TYPE)value forKey:(KEY_TYPE##KisP$S##KisP)key { -//% if (!_validationFunc(value)) { +//%DICTIONARY_VALIDATE_KEY_##KHELPER(key, ) if (!_validationFunc(value)) { //% [NSException raise:NSInvalidArgumentException //% format:@"GPB##KEY_NAME##VALUE_NAME##Dictionary: Attempt to set an unknown enum value (%d)", //% value]; @@ -900,7 +925,7 @@ void GPBDictionaryReadEntry(id mapDictionary, //%} //% //%- (void)set##ACCESSOR_NAME##VNAME$u##:(VALUE_TYPE)VNAME forKey:(KEY_TYPE##KisP$S##KisP)key { -//% [_dictionary setObject:WRAPPED##VHELPER(VNAME) forKey:WRAPPED##KHELPER(key)]; +//%DICTIONARY_VALIDATE_VALUE_##VHELPER(VNAME, )##DICTIONARY_VALIDATE_KEY_##KHELPER(key, ) [_dictionary setObject:WRAPPED##VHELPER(VNAME) forKey:WRAPPED##KHELPER(key)]; //% if (_autocreator) { //% GPBAutocreatedDictionaryModified(_autocreator, self); //% } @@ -1171,6 +1196,10 @@ void GPBDictionaryReadEntry(id mapDictionary, //% //%PDDM-DEFINE GPBVALUE_POD(VALUE_NAME) //%value##VALUE_NAME +//%PDDM-DEFINE DICTIONARY_VALIDATE_VALUE_POD(VALUE_NAME, EXTRA_INDENT) +// Empty +//%PDDM-DEFINE DICTIONARY_VALIDATE_KEY_POD(KEY_NAME, EXTRA_INDENT) +// Empty //%PDDM-DEFINE BOOL_DICT_HAS_STORAGE_POD() //% BOOL _valueSet[2]; @@ -1363,7 +1392,18 @@ void GPBDictionaryReadEntry(id mapDictionary, // Empty //%PDDM-DEFINE GPBVALUE_OBJECT(VALUE_NAME) //%valueString - +//%PDDM-DEFINE DICTIONARY_VALIDATE_VALUE_OBJECT(VALUE_NAME, EXTRA_INDENT) +//%##EXTRA_INDENT$S## if (!##VALUE_NAME) { +//%##EXTRA_INDENT$S## [NSException raise:NSInvalidArgumentException +//%##EXTRA_INDENT$S## format:@"Attempting to add nil object to a Dictionary"]; +//%##EXTRA_INDENT$S## } +//% +//%PDDM-DEFINE DICTIONARY_VALIDATE_KEY_OBJECT(KEY_NAME, EXTRA_INDENT) +//%##EXTRA_INDENT$S## if (!##KEY_NAME) { +//%##EXTRA_INDENT$S## [NSException raise:NSInvalidArgumentException +//%##EXTRA_INDENT$S## format:@"Attempting to add nil key to a Dictionary"]; +//%##EXTRA_INDENT$S## } +//% //%PDDM-DEFINE BOOL_DICT_HAS_STORAGE_OBJECT() // Empty @@ -1374,6 +1414,10 @@ void GPBDictionaryReadEntry(id mapDictionary, //% self = [super init]; //% if (self) { //% for (NSUInteger i = 0; i < count; ++i) { +//% if (!objects[i]) { +//% [NSException raise:NSInvalidArgumentException +//% format:@"Attempting to add nil object to a Dictionary"]; +//% } //% int idx = keys[i] ? 1 : 0; //% [_values[idx] release]; //% _values[idx] = (VALUE_TYPE)[objects[i] retain]; @@ -1433,6 +1477,10 @@ void GPBDictionaryReadEntry(id mapDictionary, //%} //% //%- (void)setObject:(VALUE_TYPE)object forKey:(BOOL)key { +//% if (!object) { +//% [NSException raise:NSInvalidArgumentException +//% format:@"Attempting to add nil object to a Dictionary"]; +//% } //% int idx = (key ? 1 : 0); //% [_values[idx] release]; //% _values[idx] = [object retain]; @@ -3239,6 +3287,10 @@ void GPBDictionaryReadEntry(id mapDictionary, _dictionary = [[NSMutableDictionary alloc] init]; if (count && objects && keys) { for (NSUInteger i = 0; i < count; ++i) { + if (!objects[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } [_dictionary setObject:objects[i] forKey:@(keys[i])]; } } @@ -3397,6 +3449,10 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)setObject:(id)object forKey:(uint32_t)key { + if (!object) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } [_dictionary setObject:object forKey:@(key)]; if (_autocreator) { GPBAutocreatedDictionaryModified(_autocreator, self); @@ -5195,6 +5251,10 @@ void GPBDictionaryReadEntry(id mapDictionary, _dictionary = [[NSMutableDictionary alloc] init]; if (count && objects && keys) { for (NSUInteger i = 0; i < count; ++i) { + if (!objects[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } [_dictionary setObject:objects[i] forKey:@(keys[i])]; } } @@ -5353,6 +5413,10 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)setObject:(id)object forKey:(int32_t)key { + if (!object) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } [_dictionary setObject:object forKey:@(key)]; if (_autocreator) { GPBAutocreatedDictionaryModified(_autocreator, self); @@ -7151,6 +7215,10 @@ void GPBDictionaryReadEntry(id mapDictionary, _dictionary = [[NSMutableDictionary alloc] init]; if (count && objects && keys) { for (NSUInteger i = 0; i < count; ++i) { + if (!objects[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } [_dictionary setObject:objects[i] forKey:@(keys[i])]; } } @@ -7309,6 +7377,10 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)setObject:(id)object forKey:(uint64_t)key { + if (!object) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } [_dictionary setObject:object forKey:@(key)]; if (_autocreator) { GPBAutocreatedDictionaryModified(_autocreator, self); @@ -9107,6 +9179,10 @@ void GPBDictionaryReadEntry(id mapDictionary, _dictionary = [[NSMutableDictionary alloc] init]; if (count && objects && keys) { for (NSUInteger i = 0; i < count; ++i) { + if (!objects[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } [_dictionary setObject:objects[i] forKey:@(keys[i])]; } } @@ -9265,6 +9341,10 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)setObject:(id)object forKey:(int64_t)key { + if (!object) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } [_dictionary setObject:object forKey:@(key)]; if (_autocreator) { GPBAutocreatedDictionaryModified(_autocreator, self); @@ -9336,6 +9416,10 @@ void GPBDictionaryReadEntry(id mapDictionary, _dictionary = [[NSMutableDictionary alloc] init]; if (count && values && keys) { for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } [_dictionary setObject:@(values[i]) forKey:keys[i]]; } } @@ -9474,6 +9558,10 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)setValue:(uint32_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } [_dictionary setObject:@(value) forKey:key]; if (_autocreator) { GPBAutocreatedDictionaryModified(_autocreator, self); @@ -9542,6 +9630,10 @@ void GPBDictionaryReadEntry(id mapDictionary, _dictionary = [[NSMutableDictionary alloc] init]; if (count && values && keys) { for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } [_dictionary setObject:@(values[i]) forKey:keys[i]]; } } @@ -9680,6 +9772,10 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)setValue:(int32_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } [_dictionary setObject:@(value) forKey:key]; if (_autocreator) { GPBAutocreatedDictionaryModified(_autocreator, self); @@ -9748,6 +9844,10 @@ void GPBDictionaryReadEntry(id mapDictionary, _dictionary = [[NSMutableDictionary alloc] init]; if (count && values && keys) { for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } [_dictionary setObject:@(values[i]) forKey:keys[i]]; } } @@ -9886,6 +9986,10 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)setValue:(uint64_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } [_dictionary setObject:@(value) forKey:key]; if (_autocreator) { GPBAutocreatedDictionaryModified(_autocreator, self); @@ -9954,6 +10058,10 @@ void GPBDictionaryReadEntry(id mapDictionary, _dictionary = [[NSMutableDictionary alloc] init]; if (count && values && keys) { for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } [_dictionary setObject:@(values[i]) forKey:keys[i]]; } } @@ -10092,6 +10200,10 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)setValue:(int64_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } [_dictionary setObject:@(value) forKey:key]; if (_autocreator) { GPBAutocreatedDictionaryModified(_autocreator, self); @@ -10160,6 +10272,10 @@ void GPBDictionaryReadEntry(id mapDictionary, _dictionary = [[NSMutableDictionary alloc] init]; if (count && values && keys) { for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } [_dictionary setObject:@(values[i]) forKey:keys[i]]; } } @@ -10298,6 +10414,10 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)setValue:(BOOL)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } [_dictionary setObject:@(value) forKey:key]; if (_autocreator) { GPBAutocreatedDictionaryModified(_autocreator, self); @@ -10366,6 +10486,10 @@ void GPBDictionaryReadEntry(id mapDictionary, _dictionary = [[NSMutableDictionary alloc] init]; if (count && values && keys) { for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } [_dictionary setObject:@(values[i]) forKey:keys[i]]; } } @@ -10504,6 +10628,10 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)setValue:(float)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } [_dictionary setObject:@(value) forKey:key]; if (_autocreator) { GPBAutocreatedDictionaryModified(_autocreator, self); @@ -10572,6 +10700,10 @@ void GPBDictionaryReadEntry(id mapDictionary, _dictionary = [[NSMutableDictionary alloc] init]; if (count && values && keys) { for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } [_dictionary setObject:@(values[i]) forKey:keys[i]]; } } @@ -10710,6 +10842,10 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)setValue:(double)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } [_dictionary setObject:@(value) forKey:key]; if (_autocreator) { GPBAutocreatedDictionaryModified(_autocreator, self); @@ -10802,6 +10938,10 @@ void GPBDictionaryReadEntry(id mapDictionary, _validationFunc = (func != NULL ? func : DictDefault_IsValidValue); if (count && rawValues && keys) { for (NSUInteger i = 0; i < count; ++i) { + if (!keys[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } [_dictionary setObject:@(rawValues[i]) forKey:keys[i]]; } } @@ -10982,6 +11122,10 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)setRawValue:(int32_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } [_dictionary setObject:@(value) forKey:key]; if (_autocreator) { GPBAutocreatedDictionaryModified(_autocreator, self); @@ -10997,6 +11141,10 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)setValue:(int32_t)value forKey:(NSString *)key { + if (!key) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil key to a Dictionary"]; + } if (!_validationFunc(value)) { [NSException raise:NSInvalidArgumentException format:@"GPBStringEnumDictionary: Attempt to set an unknown enum value (%d)", @@ -12754,6 +12902,10 @@ void GPBDictionaryReadEntry(id mapDictionary, self = [super init]; if (self) { for (NSUInteger i = 0; i < count; ++i) { + if (!objects[i]) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } int idx = keys[i] ? 1 : 0; [_values[idx] release]; _values[idx] = (id)[objects[i] retain]; @@ -12932,6 +13084,10 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)setObject:(id)object forKey:(BOOL)key { + if (!object) { + [NSException raise:NSInvalidArgumentException + format:@"Attempting to add nil object to a Dictionary"]; + } int idx = (key ? 1 : 0); [_values[idx] release]; _values[idx] = [object retain]; diff --git a/objectivec/GPBMessage.h b/objectivec/GPBMessage.h index d4c2fccf..332393ed 100644 --- a/objectivec/GPBMessage.h +++ b/objectivec/GPBMessage.h @@ -127,7 +127,7 @@ CF_EXTERN_C_END // Same as -[data], except a delimiter is added to the start of the data // indicating the size of the message data that follows. -- (nullable NSData *)delimitedData; +- (NSData *)delimitedData; // Returns the size of the object if it were serialized. // This is not a cached value. If you are following a pattern like this: diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m index c655edd3..d9080c3f 100644 --- a/objectivec/GPBMessage.m +++ b/objectivec/GPBMessage.m @@ -55,10 +55,15 @@ NSString *const GPBExceptionMessageKey = static NSString *const kGPBDataCoderKey = @"GPBData"; #ifndef _GPBCompileAssert -#define _GPBCompileAssertSymbolInner(line, msg) _GPBCompileAssert ## line ## __ ## msg -#define _GPBCompileAssertSymbol(line, msg) _GPBCompileAssertSymbolInner(line, msg) -#define _GPBCompileAssert(test, msg) \ - typedef char _GPBCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ] + #if __has_feature(c_static_assert) || __has_extension(c_static_assert) + #define _GPBCompileAssert(test, msg) _Static_assert((test), #msg) + #else + // Pre-Xcode 7 support. + #define _GPBCompileAssertSymbolInner(line, msg) _GPBCompileAssert ## line ## __ ## msg + #define _GPBCompileAssertSymbol(line, msg) _GPBCompileAssertSymbolInner(line, msg) + #define _GPBCompileAssert(test, msg) \ + typedef char _GPBCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ] + #endif // __has_feature(c_static_assert) || __has_extension(c_static_assert) #endif // _GPBCompileAssert // @@ -1212,7 +1217,8 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { NSLog(@"%@: Internal exception while building message delimitedData: %@", [self class], exception); #endif - data = nil; + // If it happens, truncate. + data.length = 0; } [stream release]; return data; @@ -1791,7 +1797,12 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { extensionMap_ = [[NSMutableDictionary alloc] init]; } - [extensionMap_ setObject:value forKey:extension]; + // This pointless cast is for CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION. + // Without it, the compiler complains we're passing an id nullable when + // setObject:forKey: requires a id nonnull for the value. The check for + // !value at the start of the method ensures it isn't nil, but the check + // isn't smart enough to realize that. + [extensionMap_ setObject:(id)value forKey:extension]; GPBExtensionDescriptor *descriptor = extension; diff --git a/objectivec/GPBUtilities.h b/objectivec/GPBUtilities.h index 1301b436..5b55104b 100644 --- a/objectivec/GPBUtilities.h +++ b/objectivec/GPBUtilities.h @@ -44,7 +44,7 @@ NS_ASSUME_NONNULL_BEGIN // most likely won't exactly match the original .proto file. NSString *GPBTextFormatForMessage(GPBMessage *message, NSString * __nullable lineIndent); -NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet, +NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet * __nullable unknownSet, NSString * __nullable lineIndent); // diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj index 08d0b7ef..1c834bb2 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj @@ -567,8 +567,9 @@ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftUpdateCheck = 0710; LastTestingUpgradeCheck = 0600; - LastUpgradeCheck = 0630; + LastUpgradeCheck = 0710; TargetAttributes = { 8BBEA4A5147C727100C4ADB7 = { TestTargetID = 8B9A5EA41831993600A9D33B; @@ -756,6 +757,7 @@ ); INFOPLIST_FILE = "Tests/UnitTests-Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.yourcompany.${PRODUCT_NAME:identifier}"; PRODUCT_NAME = UnitTests; SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -773,6 +775,7 @@ ); INFOPLIST_FILE = "Tests/UnitTests-Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.yourcompany.${PRODUCT_NAME:identifier}"; PRODUCT_NAME = UnitTests; SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h"; }; @@ -787,10 +790,12 @@ CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_STATIC_ANALYZER_MODE = deep; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c99; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; @@ -831,6 +836,7 @@ CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_STATIC_ANALYZER_MODE = deep; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme index 3b3eeb12..7ddf283d 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "0630" + LastUpgradeVersion = "0710" version = "1.3"> <BuildAction parallelizeBuildables = "YES" @@ -23,10 +23,10 @@ </BuildActionEntries> </BuildAction> <TestAction + buildConfiguration = "Release" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES" - buildConfiguration = "Release"> + shouldUseLaunchSchemeArgsEnv = "YES"> <Testables> <TestableReference skipped = "NO"> @@ -284,15 +284,18 @@ </SkippedTests> </TestableReference> </Testables> + <AdditionalOptions> + </AdditionalOptions> </TestAction> <LaunchAction + buildConfiguration = "Release" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" launchStyle = "0" useCustomWorkingDirectory = "NO" - buildConfiguration = "Release" ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" + debugServiceExtension = "internal" allowLocationSimulation = "YES"> <MacroExpansion> <BuildableReference @@ -307,10 +310,10 @@ </AdditionalOptions> </LaunchAction> <ProfileAction + buildConfiguration = "Release" shouldUseLaunchSchemeArgsEnv = "YES" savedToolIdentifier = "" useCustomWorkingDirectory = "NO" - buildConfiguration = "Release" debugDocumentVersioning = "YES"> <MacroExpansion> <BuildableReference diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme index 583a464a..8f510f5d 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "0630" + LastUpgradeVersion = "0710" version = "1.3"> <BuildAction parallelizeBuildables = "YES" @@ -51,10 +51,10 @@ </BuildActionEntries> </BuildAction> <TestAction + buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES" - buildConfiguration = "Debug"> + shouldUseLaunchSchemeArgsEnv = "YES"> <Testables> <TestableReference skipped = "NO"> @@ -81,15 +81,18 @@ ReferencedContainer = "container:ProtocolBuffers_OSX.xcodeproj"> </BuildableReference> </MacroExpansion> + <AdditionalOptions> + </AdditionalOptions> </TestAction> <LaunchAction + buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" launchStyle = "0" useCustomWorkingDirectory = "NO" - buildConfiguration = "Debug" ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" + debugServiceExtension = "internal" allowLocationSimulation = "YES"> <MacroExpansion> <BuildableReference @@ -104,10 +107,10 @@ </AdditionalOptions> </LaunchAction> <ProfileAction + buildConfiguration = "Release" shouldUseLaunchSchemeArgsEnv = "YES" savedToolIdentifier = "" useCustomWorkingDirectory = "NO" - buildConfiguration = "Release" debugDocumentVersioning = "YES"> <MacroExpansion> <BuildableReference diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj index 14e51037..55013641 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj @@ -644,8 +644,9 @@ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftUpdateCheck = 0710; LastTestingUpgradeCheck = 0600; - LastUpgradeCheck = 0630; + LastUpgradeCheck = 0710; TargetAttributes = { 8BBEA4A5147C727100C4ADB7 = { TestTargetID = 8B9A5EA41831993600A9D33B; @@ -865,6 +866,7 @@ CLANG_ENABLE_OBJC_ARC = YES; INFOPLIST_FILE = "$(SRCROOT)/Tests/iOSTestHarness/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 7.1; + PRODUCT_BUNDLE_IDENTIFIER = "com.google.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; WRAPPER_EXTENSION = app; @@ -879,6 +881,7 @@ CLANG_ENABLE_OBJC_ARC = YES; INFOPLIST_FILE = "$(SRCROOT)/Tests/iOSTestHarness/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 7.1; + PRODUCT_BUNDLE_IDENTIFIER = "com.google.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; WRAPPER_EXTENSION = app; @@ -949,11 +952,13 @@ CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_STATIC_ANALYZER_MODE = deep; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c99; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; @@ -994,6 +999,7 @@ CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_STATIC_ANALYZER_MODE = deep; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme index 4898eb5f..100bd828 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "0630" + LastUpgradeVersion = "0710" version = "1.3"> <BuildAction parallelizeBuildables = "YES" @@ -23,10 +23,10 @@ </BuildActionEntries> </BuildAction> <TestAction + buildConfiguration = "Release" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES" - buildConfiguration = "Release"> + shouldUseLaunchSchemeArgsEnv = "YES"> <Testables> <TestableReference skipped = "NO"> @@ -293,15 +293,18 @@ ReferencedContainer = "container:ProtocolBuffers_iOS.xcodeproj"> </BuildableReference> </MacroExpansion> + <AdditionalOptions> + </AdditionalOptions> </TestAction> <LaunchAction + buildConfiguration = "Release" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" launchStyle = "0" useCustomWorkingDirectory = "NO" - buildConfiguration = "Release" ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" + debugServiceExtension = "internal" allowLocationSimulation = "YES"> <BuildableProductRunnable runnableDebuggingMode = "0"> @@ -317,10 +320,10 @@ </AdditionalOptions> </LaunchAction> <ProfileAction + buildConfiguration = "Release" shouldUseLaunchSchemeArgsEnv = "YES" savedToolIdentifier = "" useCustomWorkingDirectory = "NO" - buildConfiguration = "Release" debugDocumentVersioning = "YES"> <MacroExpansion> <BuildableReference diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme index 19267fc3..7d219bcd 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "0630" + LastUpgradeVersion = "0710" version = "1.3"> <BuildAction parallelizeBuildables = "YES" @@ -51,10 +51,10 @@ </BuildActionEntries> </BuildAction> <TestAction + buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES" - buildConfiguration = "Debug"> + shouldUseLaunchSchemeArgsEnv = "YES"> <Testables> <TestableReference skipped = "NO"> @@ -81,15 +81,18 @@ ReferencedContainer = "container:ProtocolBuffers_iOS.xcodeproj"> </BuildableReference> </MacroExpansion> + <AdditionalOptions> + </AdditionalOptions> </TestAction> <LaunchAction + buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" launchStyle = "0" useCustomWorkingDirectory = "NO" - buildConfiguration = "Debug" ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" + debugServiceExtension = "internal" allowLocationSimulation = "YES"> <BuildableProductRunnable runnableDebuggingMode = "0"> @@ -105,10 +108,10 @@ </AdditionalOptions> </LaunchAction> <ProfileAction + buildConfiguration = "Release" shouldUseLaunchSchemeArgsEnv = "YES" savedToolIdentifier = "" useCustomWorkingDirectory = "NO" - buildConfiguration = "Release" debugDocumentVersioning = "YES"> <MacroExpansion> <BuildableReference diff --git a/objectivec/README.md b/objectivec/README.md index 134bf1ab..452feca4 100644 --- a/objectivec/README.md +++ b/objectivec/README.md @@ -13,7 +13,7 @@ Requirements The Objective C implemention requires: - Objective C 2.0 Runtime (32bit & 64bit iOS, 64bit OS X). -- Xcode 6.3 (or later). +- Xcode 7.0 (or later). - The library code does *not* use ARC (for performance reasons), but it all can be called from ARC code. diff --git a/objectivec/Tests/GPBCodedInputStreamTests.m b/objectivec/Tests/GPBCodedInputStreamTests.m index 579fe65c..7c3c006b 100644 --- a/objectivec/Tests/GPBCodedInputStreamTests.m +++ b/objectivec/Tests/GPBCodedInputStreamTests.m @@ -225,8 +225,10 @@ // Serialize and parse it. Make sure to parse from an InputStream, not // directly from a ByteString, so that CodedInputStream uses buffered // reading. + NSData *messageData = message.data; + XCTAssertNotNil(messageData); GPBCodedInputStream* stream = - [GPBCodedInputStream streamWithData:message.data]; + [GPBCodedInputStream streamWithData:messageData]; TestAllTypes* message2 = [TestAllTypes parseFromCodedInputStream:stream extensionRegistry:nil error:NULL]; diff --git a/objectivec/Tests/GPBMessageTests+Serialization.m b/objectivec/Tests/GPBMessageTests+Serialization.m index 4dcca7a3..0d811a96 100644 --- a/objectivec/Tests/GPBMessageTests+Serialization.m +++ b/objectivec/Tests/GPBMessageTests+Serialization.m @@ -121,8 +121,9 @@ static NSData *DataFromCStr(const char *str) { fooWithExtras.enumValue = DropUnknownsFooWithExtraFields_NestedEnum_Baz; fooWithExtras.extraInt32Value = 2; - DropUnknownsFoo *foo = - [DropUnknownsFoo parseFromData:[fooWithExtras data] error:NULL]; + NSData *data = [fooWithExtras data]; + XCTAssertNotNil(data); + DropUnknownsFoo *foo = [DropUnknownsFoo parseFromData:data error:NULL]; XCTAssertEqual(foo.int32Value, 1); XCTAssertEqual(foo.enumValue, DropUnknownsFoo_NestedEnum_Baz); @@ -130,8 +131,9 @@ static NSData *DataFromCStr(const char *str) { XCTAssertEqual([foo.unknownFields countOfFields], 0U); [fooWithExtras release]; + data = [foo data]; fooWithExtras = - [DropUnknownsFooWithExtraFields parseFromData:[foo data] error:NULL]; + [DropUnknownsFooWithExtraFields parseFromData:data error:NULL]; XCTAssertEqual(fooWithExtras.int32Value, 1); XCTAssertEqual(fooWithExtras.enumValue, DropUnknownsFooWithExtraFields_NestedEnum_Baz); @@ -149,7 +151,9 @@ static NSData *DataFromCStr(const char *str) { rawValue:Message3_Enum_Extra3]; orig.oneofEnum = Message3_Enum_Extra3; - Message2 *msg = [[Message2 alloc] initWithData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [[Message2 alloc] initWithData:data error:NULL]; // None of the fields should be set. @@ -201,8 +205,10 @@ static NSData *DataFromCStr(const char *str) { // Everything should be there via raw values. + NSData *data = [orig data]; + XCTAssertNotNil(data); UnknownEnumsMyMessage *msg = - [UnknownEnumsMyMessage parseFromData:[orig data] error:NULL]; + [UnknownEnumsMyMessage parseFromData:data error:NULL]; XCTAssertEqual(msg.e, UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue); XCTAssertEqual(UnknownEnumsMyMessage_E_RawValue(msg), @@ -224,7 +230,8 @@ static NSData *DataFromCStr(const char *str) { // Everything should go out and come back. - orig = [UnknownEnumsMyMessagePlusExtra parseFromData:[msg data] error:NULL]; + data = [msg data]; + orig = [UnknownEnumsMyMessagePlusExtra parseFromData:data error:NULL]; XCTAssertEqual(orig.e, UnknownEnumsMyEnumPlusExtra_EExtra); XCTAssertEqual(orig.repeatedEArray.count, 1U); @@ -243,7 +250,9 @@ static NSData *DataFromCStr(const char *str) { //% MESSAGE *orig = [[MESSAGE alloc] init]; //% orig.oneof##FIELD = VALUE; //% XCTAssertEqual(orig.oOneOfCase, MESSAGE##_O_OneOfCase_Oneof##FIELD); -//% MESSAGE *msg = [MESSAGE parseFromData:[orig data] error:NULL]; +//% NSData *data = [orig data]; +//% XCTAssertNotNil(data); +//% MESSAGE *msg = [MESSAGE parseFromData:data error:NULL]; //% XCTAssertEqual(msg.oOneOfCase, MESSAGE##_O_OneOfCase_Oneof##FIELD); //% XCTAssertEqual##EQ_SUFFIX(msg.oneof##FIELD, VALUE); //% [orig release]; @@ -311,7 +320,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofInt32 = 1; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofInt32); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt32); XCTAssertEqual(msg.oneofInt32, 1); [orig release]; @@ -321,7 +332,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofInt64 = 2; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofInt64); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt64); XCTAssertEqual(msg.oneofInt64, 2); [orig release]; @@ -331,7 +344,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofUint32 = 3U; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofUint32); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint32); XCTAssertEqual(msg.oneofUint32, 3U); [orig release]; @@ -341,7 +356,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofUint64 = 4U; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofUint64); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint64); XCTAssertEqual(msg.oneofUint64, 4U); [orig release]; @@ -351,7 +368,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofSint32 = 5; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSint32); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint32); XCTAssertEqual(msg.oneofSint32, 5); [orig release]; @@ -361,7 +380,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofSint64 = 6; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSint64); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint64); XCTAssertEqual(msg.oneofSint64, 6); [orig release]; @@ -371,7 +392,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofFixed32 = 7U; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofFixed32); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed32); XCTAssertEqual(msg.oneofFixed32, 7U); [orig release]; @@ -381,7 +404,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofFixed64 = 8U; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofFixed64); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed64); XCTAssertEqual(msg.oneofFixed64, 8U); [orig release]; @@ -391,7 +416,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofSfixed32 = 9; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32); XCTAssertEqual(msg.oneofSfixed32, 9); [orig release]; @@ -401,7 +428,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofSfixed64 = 10; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64); XCTAssertEqual(msg.oneofSfixed64, 10); [orig release]; @@ -411,7 +440,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofFloat = 11.0f; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofFloat); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFloat); XCTAssertEqual(msg.oneofFloat, 11.0f); [orig release]; @@ -421,7 +452,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofDouble = 12.0; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofDouble); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofDouble); XCTAssertEqual(msg.oneofDouble, 12.0); [orig release]; @@ -431,7 +464,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofBool = NO; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofBool); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBool); XCTAssertEqual(msg.oneofBool, NO); [orig release]; @@ -441,7 +476,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofString = @"foo"; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofString); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofString); XCTAssertEqualObjects(msg.oneofString, @"foo"); [orig release]; @@ -451,7 +488,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding]; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofBytes); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBytes); XCTAssertEqualObjects(msg.oneofBytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding]); [orig release]; @@ -461,7 +500,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofGroup = group; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofGroup); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofGroup); XCTAssertEqualObjects(msg.oneofGroup, group); [orig release]; @@ -471,7 +512,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofMessage = subMessage; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofMessage); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofMessage); XCTAssertEqualObjects(msg.oneofMessage, subMessage); [orig release]; @@ -481,7 +524,9 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofEnum = Message2_Enum_Bar; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofEnum); - Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message2 *msg = [Message2 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofEnum); XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar); [orig release]; @@ -504,7 +549,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofInt32 = 1; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofInt32); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt32); XCTAssertEqual(msg.oneofInt32, 1); [orig release]; @@ -514,7 +561,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofInt64 = 2; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofInt64); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt64); XCTAssertEqual(msg.oneofInt64, 2); [orig release]; @@ -524,7 +573,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofUint32 = 3U; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofUint32); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint32); XCTAssertEqual(msg.oneofUint32, 3U); [orig release]; @@ -534,7 +585,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofUint64 = 4U; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofUint64); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint64); XCTAssertEqual(msg.oneofUint64, 4U); [orig release]; @@ -544,7 +597,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofSint32 = 5; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSint32); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint32); XCTAssertEqual(msg.oneofSint32, 5); [orig release]; @@ -554,7 +609,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofSint64 = 6; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSint64); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint64); XCTAssertEqual(msg.oneofSint64, 6); [orig release]; @@ -564,7 +621,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofFixed32 = 7U; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofFixed32); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed32); XCTAssertEqual(msg.oneofFixed32, 7U); [orig release]; @@ -574,7 +633,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofFixed64 = 8U; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofFixed64); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed64); XCTAssertEqual(msg.oneofFixed64, 8U); [orig release]; @@ -584,7 +645,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofSfixed32 = 9; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32); XCTAssertEqual(msg.oneofSfixed32, 9); [orig release]; @@ -594,7 +657,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofSfixed64 = 10; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64); XCTAssertEqual(msg.oneofSfixed64, 10); [orig release]; @@ -604,7 +669,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofFloat = 11.0f; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofFloat); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFloat); XCTAssertEqual(msg.oneofFloat, 11.0f); [orig release]; @@ -614,7 +681,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofDouble = 12.0; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofDouble); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofDouble); XCTAssertEqual(msg.oneofDouble, 12.0); [orig release]; @@ -624,7 +693,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofBool = YES; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofBool); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBool); XCTAssertEqual(msg.oneofBool, YES); [orig release]; @@ -634,7 +705,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofString = @"foo"; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofString); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofString); XCTAssertEqualObjects(msg.oneofString, @"foo"); [orig release]; @@ -644,7 +717,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding]; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofBytes); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBytes); XCTAssertEqualObjects(msg.oneofBytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding]); [orig release]; @@ -656,7 +731,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofMessage = subMessage; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofMessage); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofMessage); XCTAssertEqualObjects(msg.oneofMessage, subMessage); [orig release]; @@ -666,7 +743,9 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofEnum = Message2_Enum_Bar; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofEnum); - Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + Message3 *msg = [Message3 parseFromData:data error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofEnum); XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar); [orig release]; @@ -927,15 +1006,18 @@ static NSData *DataFromCStr(const char *str) { [orig.unknownMapField setValue:Proto2MapEnumPlusExtra_EProto2MapEnumExtra forKey:0]; - TestEnumMap *msg1 = [TestEnumMap parseFromData:[orig data] error:NULL]; + NSData *data = [orig data]; + XCTAssertNotNil(data); + TestEnumMap *msg1 = [TestEnumMap parseFromData:data error:NULL]; XCTAssertEqual(msg1.knownMapField.count, 1U); int32_t val = -1; XCTAssertTrue([msg1.knownMapField valueForKey:0 value:&val]); XCTAssertEqual(val, Proto2MapEnum_Proto2MapEnumFoo); XCTAssertEqual(msg1.unknownFields.countOfFields, 1U); + data = [msg1 data]; TestEnumMapPlusExtra *msg2 = - [TestEnumMapPlusExtra parseFromData:[msg1 data] error:NULL]; + [TestEnumMapPlusExtra parseFromData:data error:NULL]; val = -1; XCTAssertEqual(msg2.knownMapField.count, 1U); XCTAssertTrue([msg2.knownMapField valueForKey:0 value:&val]); @@ -1006,6 +1088,7 @@ static NSData *DataFromCStr(const char *str) { [msg.mapInt32Message setObject:val4 forKey:2035]; NSData *data = [msg data]; + XCTAssertNotNil(data); Message2 *msg2 = [[Message2 alloc] initWithData:data error:NULL]; XCTAssertNotEqual(msg2, msg); // Pointer comparison diff --git a/objectivec/Tests/GPBMessageTests.m b/objectivec/Tests/GPBMessageTests.m index cd0de8fc..f79b8128 100644 --- a/objectivec/Tests/GPBMessageTests.m +++ b/objectivec/Tests/GPBMessageTests.m @@ -195,7 +195,9 @@ // Test merging from data. result = [self mergeExtensionsDestination]; - [result mergeFromData:[[self mergeExtensionsSource] data] + NSData *data = [[self mergeExtensionsSource] data]; + XCTAssertNotNil(data); + [result mergeFromData:data extensionRegistry:[UnittestRoot extensionRegistry]]; resultData = [result data]; XCTAssertEqualObjects(resultData, mergeResultData); @@ -1884,7 +1886,9 @@ XCTAssertEqual(msg.bar, EnumTestMsg_MyEnum_One); XCTAssertEqual(msg.baz, EnumTestMsg_MyEnum_NegOne); // Bounce to wire and back. - EnumTestMsg *msgPrime = [EnumTestMsg parseFromData:[msg data] error:NULL]; + NSData *data = [msg data]; + XCTAssertNotNil(data); + EnumTestMsg *msgPrime = [EnumTestMsg parseFromData:data error:NULL]; XCTAssertEqualObjects(msgPrime, msg); XCTAssertEqual(msgPrime.foo, EnumTestMsg_MyEnum_Zero); XCTAssertEqual(msgPrime.bar, EnumTestMsg_MyEnum_One); @@ -1896,7 +1900,9 @@ XCTAssertEqual(msg.bar, EnumTestMsg_MyEnum_Two); XCTAssertEqual(msg.baz, EnumTestMsg_MyEnum_NegTwo); // Bounce to wire and back. - msgPrime = [EnumTestMsg parseFromData:[msg data] error:NULL]; + data = [msg data]; + XCTAssertNotNil(data); + msgPrime = [EnumTestMsg parseFromData:data error:NULL]; XCTAssertEqualObjects(msgPrime, msg); XCTAssertEqual(msgPrime.foo, EnumTestMsg_MyEnum_Zero); XCTAssertEqual(msgPrime.bar, EnumTestMsg_MyEnum_Two); @@ -1917,7 +1923,9 @@ XCTAssertEqual([msg.mumbleArray valueAtIndex:3], EnumTestMsg_MyEnum_NegOne); XCTAssertEqual([msg.mumbleArray valueAtIndex:4], EnumTestMsg_MyEnum_NegTwo); // Bounce to wire and back. - msgPrime = [EnumTestMsg parseFromData:[msg data] error:NULL]; + data = [msg data]; + XCTAssertNotNil(data); + msgPrime = [EnumTestMsg parseFromData:data error:NULL]; XCTAssertEqualObjects(msgPrime, msg); XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:0], EnumTestMsg_MyEnum_Zero); diff --git a/objectivec/Tests/GPBSwiftTests.swift b/objectivec/Tests/GPBSwiftTests.swift index 5fbe74fd..36ed2a62 100644 --- a/objectivec/Tests/GPBSwiftTests.swift +++ b/objectivec/Tests/GPBSwiftTests.swift @@ -83,8 +83,8 @@ class GPBBridgeTests: XCTestCase { XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(0), Int32(300)) XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(1), Int32(301)) XCTAssertEqual(msg.repeatedStringArray.count, Int(2)) - XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(0) as! String, "mno") - XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(1) as! String, "pqr") + XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(0) as? String, "mno") + XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(1) as? String, "pqr") XCTAssertEqual(msg.repeatedEnumArray.count, UInt(2)) XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(0), Message2_Enum.Bar.rawValue) XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(1), Message2_Enum.Baz.rawValue) @@ -96,8 +96,8 @@ class GPBBridgeTests: XCTestCase { XCTAssertTrue(msg.mapInt32Int32.valueForKey(501, value:&intValue)) XCTAssertEqual(intValue, Int32(401)) XCTAssertEqual(msg.mapStringString.count, Int(2)) - XCTAssertEqual(msg.mapStringString.objectForKey("bar") as! String, "foo") - XCTAssertEqual(msg.mapStringString.objectForKey("xyz") as! String, "abc") + XCTAssertEqual(msg.mapStringString.objectForKey("bar") as? String, "foo") + XCTAssertEqual(msg.mapStringString.objectForKey("xyz") as? String, "abc") XCTAssertEqual(msg.mapInt32Enum.count, UInt(2)) XCTAssertTrue(msg.mapInt32Enum.valueForKey(600, value:&intValue)) XCTAssertEqual(intValue, Message2_Enum.Bar.rawValue) @@ -173,8 +173,8 @@ class GPBBridgeTests: XCTestCase { XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(0), Int32(300)) XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(1), Int32(301)) XCTAssertEqual(msg.repeatedStringArray.count, Int(2)) - XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(0) as! String, "mno") - XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(1) as! String, "pqr") + XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(0) as? String, "mno") + XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(1) as? String, "pqr") XCTAssertEqual(msg.repeatedInt64Array.count, UInt(0)) XCTAssertEqual(msg.repeatedEnumArray.count, UInt(2)) XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(0), Message3_Enum.Bar.rawValue) @@ -189,8 +189,8 @@ class GPBBridgeTests: XCTestCase { XCTAssertTrue(msg.mapInt32Int32.valueForKey(501, value:&intValue)) XCTAssertEqual(intValue, Int32(401)) XCTAssertEqual(msg.mapStringString.count, Int(2)) - XCTAssertEqual(msg.mapStringString.objectForKey("bar") as! String, "foo") - XCTAssertEqual(msg.mapStringString.objectForKey("xyz") as! String, "abc") + XCTAssertEqual(msg.mapStringString.objectForKey("bar") as? String, "foo") + XCTAssertEqual(msg.mapStringString.objectForKey("xyz") as? String, "abc") XCTAssertEqual(msg.mapInt32Enum.count, UInt(2)) XCTAssertTrue(msg.mapInt32Enum.valueForKey(600, value:&intValue)) XCTAssertEqual(intValue, Message2_Enum.Bar.rawValue) diff --git a/objectivec/Tests/UnitTests-Info.plist b/objectivec/Tests/UnitTests-Info.plist index 65013556..460a7d93 100644 --- a/objectivec/Tests/UnitTests-Info.plist +++ b/objectivec/Tests/UnitTests-Info.plist @@ -7,7 +7,7 @@ <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleIdentifier</key> - <string>com.yourcompany.${PRODUCT_NAME:identifier}</string> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundlePackageType</key> diff --git a/objectivec/Tests/iOSTestHarness/Info.plist b/objectivec/Tests/iOSTestHarness/Info.plist index 31ab1578..24bd333d 100644 --- a/objectivec/Tests/iOSTestHarness/Info.plist +++ b/objectivec/Tests/iOSTestHarness/Info.plist @@ -9,7 +9,7 @@ <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleIdentifier</key> - <string>com.google.${PRODUCT_NAME:rfc1034identifier}</string> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> diff --git a/objectivec/google/protobuf/Any.pbobjc.h b/objectivec/google/protobuf/Any.pbobjc.h index 6511b8ed..d2261ee4 100644 --- a/objectivec/google/protobuf/Any.pbobjc.h +++ b/objectivec/google/protobuf/Any.pbobjc.h @@ -4,7 +4,7 @@ #import "GPBProtocolBuffers.h" #if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 -#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif // @@protoc_insertion_point(imports) diff --git a/objectivec/google/protobuf/Api.pbobjc.h b/objectivec/google/protobuf/Api.pbobjc.h index d6292cba..c9dacfee 100644 --- a/objectivec/google/protobuf/Api.pbobjc.h +++ b/objectivec/google/protobuf/Api.pbobjc.h @@ -4,7 +4,7 @@ #import "GPBProtocolBuffers.h" #if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 -#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif // @@protoc_insertion_point(imports) diff --git a/objectivec/google/protobuf/Descriptor.pbobjc.h b/objectivec/google/protobuf/Descriptor.pbobjc.h index 70cb7447..f04616c3 100644 --- a/objectivec/google/protobuf/Descriptor.pbobjc.h +++ b/objectivec/google/protobuf/Descriptor.pbobjc.h @@ -4,7 +4,7 @@ #import "GPBProtocolBuffers.h" #if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 -#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif // @@protoc_insertion_point(imports) diff --git a/objectivec/google/protobuf/Duration.pbobjc.h b/objectivec/google/protobuf/Duration.pbobjc.h index 9ecba197..b592640b 100644 --- a/objectivec/google/protobuf/Duration.pbobjc.h +++ b/objectivec/google/protobuf/Duration.pbobjc.h @@ -4,7 +4,7 @@ #import "GPBProtocolBuffers.h" #if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 -#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif // @@protoc_insertion_point(imports) diff --git a/objectivec/google/protobuf/Empty.pbobjc.h b/objectivec/google/protobuf/Empty.pbobjc.h index ff7f384a..bace614d 100644 --- a/objectivec/google/protobuf/Empty.pbobjc.h +++ b/objectivec/google/protobuf/Empty.pbobjc.h @@ -4,7 +4,7 @@ #import "GPBProtocolBuffers.h" #if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 -#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif // @@protoc_insertion_point(imports) diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.h b/objectivec/google/protobuf/FieldMask.pbobjc.h index 0cdbd574..67cea4d6 100644 --- a/objectivec/google/protobuf/FieldMask.pbobjc.h +++ b/objectivec/google/protobuf/FieldMask.pbobjc.h @@ -4,7 +4,7 @@ #import "GPBProtocolBuffers.h" #if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 -#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif // @@protoc_insertion_point(imports) diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.h b/objectivec/google/protobuf/SourceContext.pbobjc.h index 6bc57149..8480db1d 100644 --- a/objectivec/google/protobuf/SourceContext.pbobjc.h +++ b/objectivec/google/protobuf/SourceContext.pbobjc.h @@ -4,7 +4,7 @@ #import "GPBProtocolBuffers.h" #if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 -#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif // @@protoc_insertion_point(imports) diff --git a/objectivec/google/protobuf/Struct.pbobjc.h b/objectivec/google/protobuf/Struct.pbobjc.h index 7513cf90..f40414fa 100644 --- a/objectivec/google/protobuf/Struct.pbobjc.h +++ b/objectivec/google/protobuf/Struct.pbobjc.h @@ -4,7 +4,7 @@ #import "GPBProtocolBuffers.h" #if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 -#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif // @@protoc_insertion_point(imports) diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.h b/objectivec/google/protobuf/Timestamp.pbobjc.h index a1f68bd2..79b24ec6 100644 --- a/objectivec/google/protobuf/Timestamp.pbobjc.h +++ b/objectivec/google/protobuf/Timestamp.pbobjc.h @@ -4,7 +4,7 @@ #import "GPBProtocolBuffers.h" #if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 -#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif // @@protoc_insertion_point(imports) diff --git a/objectivec/google/protobuf/Type.pbobjc.h b/objectivec/google/protobuf/Type.pbobjc.h index 44ef05c5..65f1da46 100644 --- a/objectivec/google/protobuf/Type.pbobjc.h +++ b/objectivec/google/protobuf/Type.pbobjc.h @@ -4,7 +4,7 @@ #import "GPBProtocolBuffers.h" #if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 -#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif // @@protoc_insertion_point(imports) diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.h b/objectivec/google/protobuf/Wrappers.pbobjc.h index a9a260bc..580945c4 100644 --- a/objectivec/google/protobuf/Wrappers.pbobjc.h +++ b/objectivec/google/protobuf/Wrappers.pbobjc.h @@ -4,7 +4,7 @@ #import "GPBProtocolBuffers.h" #if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 -#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif // @@protoc_insertion_point(imports) diff --git a/protobuf.bzl b/protobuf.bzl index 86c6f251..bf748db6 100644 --- a/protobuf.bzl +++ b/protobuf.bzl @@ -141,6 +141,7 @@ def cc_proto_library( deps=[s + "_genproto" for s in deps], includes=includes, protoc=protoc, + visibility=["//visibility:public"], ) # An empty cc_library to make rule dependency consistent. native.cc_library( @@ -157,6 +158,7 @@ def cc_proto_library( protoc=protoc, gen_cc=1, outs=outs, + visibility=["//visibility:public"], ) if default_runtime and not default_runtime in cc_libs: @@ -245,6 +247,7 @@ def py_proto_library( protoc=protoc, gen_py=1, outs=outs, + visibility=["//visibility:public"], ) if include != None: diff --git a/python/google/protobuf/pyext/extension_dict.h b/python/google/protobuf/pyext/extension_dict.h index 7e1049f1..7a66cb23 100644 --- a/python/google/protobuf/pyext/extension_dict.h +++ b/python/google/protobuf/pyext/extension_dict.h @@ -47,7 +47,11 @@ namespace protobuf { class Message; class FieldDescriptor; +#ifdef _SHARED_PTR_H +using std::shared_ptr; +#else using internal::shared_ptr; +#endif namespace python { diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h index 1ff82e2f..94de4551 100644 --- a/python/google/protobuf/pyext/message.h +++ b/python/google/protobuf/pyext/message.h @@ -52,7 +52,12 @@ class Descriptor; class DescriptorPool; class MessageFactory; +#ifdef _SHARED_PTR_H +using std::shared_ptr; +using std::string; +#else using internal::shared_ptr; +#endif namespace python { diff --git a/python/google/protobuf/pyext/message_map_container.h b/python/google/protobuf/pyext/message_map_container.h index 8286ba8a..4f6cb26a 100644 --- a/python/google/protobuf/pyext/message_map_container.h +++ b/python/google/protobuf/pyext/message_map_container.h @@ -45,7 +45,11 @@ namespace protobuf { class Message; +#ifdef _SHARED_PTR_H +using std::shared_ptr; +#else using internal::shared_ptr; +#endif namespace python { diff --git a/python/google/protobuf/pyext/repeated_composite_container.h b/python/google/protobuf/pyext/repeated_composite_container.h index 3013aba9..58d37b02 100644 --- a/python/google/protobuf/pyext/repeated_composite_container.h +++ b/python/google/protobuf/pyext/repeated_composite_container.h @@ -49,7 +49,11 @@ namespace protobuf { class FieldDescriptor; class Message; +#ifdef _SHARED_PTR_H +using std::shared_ptr; +#else using internal::shared_ptr; +#endif namespace python { diff --git a/python/google/protobuf/pyext/repeated_scalar_container.h b/python/google/protobuf/pyext/repeated_scalar_container.h index 5dfa21e0..555e621c 100644 --- a/python/google/protobuf/pyext/repeated_scalar_container.h +++ b/python/google/protobuf/pyext/repeated_scalar_container.h @@ -48,7 +48,11 @@ namespace protobuf { class Message; +#ifdef _SHARED_PTR_H +using std::shared_ptr; +#else using internal::shared_ptr; +#endif namespace python { diff --git a/python/google/protobuf/pyext/scalar_map_container.h b/python/google/protobuf/pyext/scalar_map_container.h index aded8d49..4d663b88 100644 --- a/python/google/protobuf/pyext/scalar_map_container.h +++ b/python/google/protobuf/pyext/scalar_map_container.h @@ -45,7 +45,11 @@ namespace protobuf { class Message; +#ifdef _SHARED_PTR_H +using std::shared_ptr; +#else using internal::shared_ptr; +#endif namespace python { diff --git a/python/setup.py b/python/setup.py index 9a7eaddf..18865e03 100755 --- a/python/setup.py +++ b/python/setup.py @@ -144,6 +144,12 @@ class build_py(_build_py): # _build_py is an old-style class, so super() doesn't work. _build_py.run(self) +class test_conformance(_build_py): + target = 'test_python' + def run(self): + cmd = 'cd ../conformance && make %s' % (test_conformance.target) + status = subprocess.check_call(cmd, shell=True) + if __name__ == '__main__': ext_module_list = [] @@ -152,6 +158,7 @@ if __name__ == '__main__': if cpp_impl in sys.argv: sys.argv.remove(cpp_impl) extra_compile_args = ['-Wno-write-strings', '-Wno-invalid-offsetof'] + test_conformance.target = 'test_python_cpp' if "clang" in os.popen('$CC --version').read(): extra_compile_args.append('-Wno-shorten-64-to-32') @@ -207,6 +214,7 @@ if __name__ == '__main__': cmdclass={ 'clean': clean, 'build_py': build_py, + 'test_conformance': test_conformance, }, install_requires=install_requires, ext_modules=ext_module_list, diff --git a/python/tox.ini b/python/tox.ini index a05460b5..683d82dc 100644 --- a/python/tox.ini +++ b/python/tox.ini @@ -15,6 +15,8 @@ commands = cpp: python setup.py -q build --cpp_implementation --warnings_as_errors python: python setup.py -q test -q cpp: python setup.py -q test -q --cpp_implementation + python: python setup.py -q test_conformance + cpp: python setup.py -q test_conformance --cpp_implementation deps = # Keep this list of dependencies in sync with setup.py. six @@ -8,5 +8,6 @@ genrule( py_library( name = "six", srcs = ["six.py"], + srcs_version = "PY2AND3", visibility = ["//visibility:public"], ) diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc index cbb5d233..321fd315 100644 --- a/src/google/protobuf/any.pb.cc +++ b/src/google/protobuf/any.pb.cc @@ -2,7 +2,7 @@ // source: google/protobuf/any.proto #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION -#include "google/protobuf/any.pb.h" +#include <google/protobuf/any.pb.h> #include <algorithm> @@ -119,10 +119,10 @@ bool Any::UnpackTo(::google::protobuf::Message* message) const { return _any_metadata_.UnpackTo(message); } -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int Any::kTypeUrlFieldNumber; const int Any::kValueFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 Any::Any() : ::google::protobuf::Message(), _internal_metadata_(NULL), _any_metadata_(&type_url_, &value_) { diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h index c324c4af..97982ecf 100644 --- a/src/google/protobuf/any.pb.h +++ b/src/google/protobuf/any.pb.h @@ -27,7 +27,7 @@ #include <google/protobuf/repeated_field.h> #include <google/protobuf/extension_set.h> #include <google/protobuf/unknown_field_set.h> -#include "google/protobuf/any.h" +#include <google/protobuf/any.h> // @@protoc_insertion_point(includes) namespace google { diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc index 0a2c4ec0..ed90702c 100644 --- a/src/google/protobuf/api.pb.cc +++ b/src/google/protobuf/api.pb.cc @@ -2,7 +2,7 @@ // source: google/protobuf/api.proto #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION -#include "google/protobuf/api.pb.h" +#include <google/protobuf/api.pb.h> #include <algorithm> @@ -186,7 +186,7 @@ static void MergeFromFail(int line) { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int Api::kNameFieldNumber; const int Api::kMethodsFieldNumber; const int Api::kOptionsFieldNumber; @@ -194,7 +194,7 @@ const int Api::kVersionFieldNumber; const int Api::kSourceContextFieldNumber; const int Api::kMixinsFieldNumber; const int Api::kSyntaxFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 Api::Api() : ::google::protobuf::Message(), _internal_metadata_(NULL) { @@ -904,7 +904,7 @@ void Api::clear_syntax() { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int Method::kNameFieldNumber; const int Method::kRequestTypeUrlFieldNumber; const int Method::kRequestStreamingFieldNumber; @@ -912,7 +912,7 @@ const int Method::kResponseTypeUrlFieldNumber; const int Method::kResponseStreamingFieldNumber; const int Method::kOptionsFieldNumber; const int Method::kSyntaxFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 Method::Method() : ::google::protobuf::Message(), _internal_metadata_(NULL) { @@ -1608,10 +1608,10 @@ void Method::clear_syntax() { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int Mixin::kNameFieldNumber; const int Mixin::kRootFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 Mixin::Mixin() : ::google::protobuf::Message(), _internal_metadata_(NULL) { diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h index 3c5a6f31..e1dca4e4 100644 --- a/src/google/protobuf/api.pb.h +++ b/src/google/protobuf/api.pb.h @@ -27,8 +27,8 @@ #include <google/protobuf/repeated_field.h> #include <google/protobuf/extension_set.h> #include <google/protobuf/unknown_field_set.h> -#include "google/protobuf/source_context.pb.h" -#include "google/protobuf/type.pb.h" +#include <google/protobuf/source_context.pb.h> +#include <google/protobuf/type.pb.h> // @@protoc_insertion_point(includes) namespace google { diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index 16e0d50e..40c1e7c2 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -490,27 +490,28 @@ class LIBPROTOBUF_EXPORT Arena { return GetArenaInternal(value, static_cast<T*>(0)); } - // Helper typetrait that indicates support for arenas in a type T at compile - // time. This is public only to allow construction of higher-level templated - // utilities. is_arena_constructable<T>::value is an instance of - // google::protobuf::internal::true_type if the message type T has arena support enabled, and - // google::protobuf::internal::false_type otherwise. - // - // This is inside Arena because only Arena has the friend relationships - // necessary to see the underlying generated code traits. - template<typename T> - struct is_arena_constructable { + private: + struct InternalIsArenaConstructableHelper { template<typename U> static char ArenaConstructable( const typename U::InternalArenaConstructable_*); template<typename U> static double ArenaConstructable(...); + }; - // This will resolve to either google::protobuf::internal::true_type or google::protobuf::internal::false_type. - typedef google::protobuf::internal::integral_constant<bool, - sizeof(ArenaConstructable<const T>(static_cast<const T*>(0))) == - sizeof(char)> type; - static const type value; + public: + // Helper typetrait that indicates support for arenas in a type T at compile + // time. This is public only to allow construction of higher-level templated + // utilities. is_arena_constructable<T>::value is true if the message type T + // has arena support enabled, and false otherwise. + // + // This is inside Arena because only Arena has the friend relationships + // necessary to see the underlying generated code traits. + template<typename T> + struct is_arena_constructable : + public google::protobuf::internal::integral_constant<bool, + sizeof(InternalIsArenaConstructableHelper::ArenaConstructable< + const T>(static_cast<const T*>(0))) == sizeof(char)> { }; private: @@ -572,32 +573,30 @@ class LIBPROTOBUF_EXPORT Arena { return google::protobuf::internal::has_trivial_destructor<T>::value; } - // Helper typetrait that indicates whether the desctructor of type T should be - // called when arena is destroyed at compile time. This is only to allow - // construction of higher-level templated utilities. - // is_destructor_skippable<T>::value is an instance of google::protobuf::internal::true_type if the - // destructor of the message type T should not be called when arena is - // destroyed or google::protobuf::internal::has_trivial_destructor<T>::value == true, and - // google::protobuf::internal::false_type otherwise. - // - // This is inside Arena because only Arena has the friend relationships - // necessary to see the underlying generated code traits. - template<typename T> - struct is_destructor_skippable { + private: + struct InternalIsDestructorSkippableHelper { template<typename U> static char DestructorSkippable( const typename U::DestructorSkippable_*); template<typename U> static double DestructorSkippable(...); + }; - // The raw_skippable_value const bool variable is separated from the typedef - // line below as a work-around of an NVCC 7.0 (and earlier) compiler bug. - static const bool raw_skippable_value = - sizeof(DestructorSkippable<const T>(static_cast<const T*>(0))) == - sizeof(char) || google::protobuf::internal::has_trivial_destructor<T>::value == true; - // This will resolve to either google::protobuf::internal::true_type or google::protobuf::internal::false_type. - typedef google::protobuf::internal::integral_constant<bool, raw_skippable_value> type; - static const type value; + public: + // Helper typetrait that indicates whether the desctructor of type T should be + // called when arena is destroyed at compile time. This is only to allow + // construction of higher-level templated utilities. + // is_destructor_skippable<T>::value is true if the destructor of the message + // type T should not be called when arena is destroyed or false otherwise. + // This is inside Arena because only Arena has the friend relationships + // necessary to see the underlying generated code traits. + template<typename T> + struct is_destructor_skippable : + public google::protobuf::internal::integral_constant<bool, + sizeof(InternalIsDestructorSkippableHelper::DestructorSkippable< + const T>(static_cast<const T*>(0))) == + sizeof(char) || + google::protobuf::internal::has_trivial_destructor<T>::value> { }; @@ -780,8 +779,10 @@ class LIBPROTOBUF_EXPORT Arena { // which needs to declare google::protobuf::Map as friend of generated message. template <typename T> static void CreateInArenaStorage(T* ptr, Arena* arena) { - CreateInArenaStorageInternal(ptr, arena, is_arena_constructable<T>::value); - RegisterDestructorInternal(ptr, arena, is_destructor_skippable<T>::value); + CreateInArenaStorageInternal(ptr, arena, + typename is_arena_constructable<T>::type()); + RegisterDestructorInternal(ptr, arena, + typename is_destructor_skippable<T>::type()); } template <typename T> @@ -910,16 +911,6 @@ class LIBPROTOBUF_EXPORT Arena { // Defined above for supporting environments without RTTI. #undef RTTI_TYPE_ID -template<typename T> -const typename Arena::is_arena_constructable<T>::type - Arena::is_arena_constructable<T>::value = - typename Arena::is_arena_constructable<T>::type(); - -template<typename T> -const typename Arena::is_destructor_skippable<T>::type - Arena::is_destructor_skippable<T>::value = - typename Arena::is_destructor_skippable<T>::type(); - } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index 4906985d..9aa41534 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -237,6 +237,7 @@ void FileGenerator::GeneratePBHeader(io::Printer* printer) { } void FileGenerator::GenerateSource(io::Printer* printer) { + bool well_known = IsWellKnownMessage(file_); string header = StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h"); printer->Print( @@ -246,7 +247,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) { // The generated code calls accessors that might be deprecated. We don't // want the compiler to warn in generated code. "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n" - "#include \"$header$\"\n" + "#include $left$$header$$right$\n" "\n" "#include <algorithm>\n" // for swap() "\n" @@ -255,7 +256,9 @@ void FileGenerator::GenerateSource(io::Printer* printer) { "#include <google/protobuf/io/coded_stream.h>\n" "#include <google/protobuf/wire_format_lite_inl.h>\n", "filename", file_->name(), - "header", header); + "header", header, + "left", well_known ? "<" : "\"", + "right", well_known ? ">" : "\""); // Unknown fields implementation in lite mode uses StringOutputStream if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) { @@ -857,14 +860,16 @@ void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) { } for (int i = 0; i < file_->dependency_count(); i++) { + bool well_known = IsWellKnownMessage(file_->dependency(i)); const string& name = file_->dependency(i)->name(); bool public_import = (public_import_names.count(name) != 0); - printer->Print( - "#include \"$dependency$.pb.h\"$iwyu$\n", + "#include $left$$dependency$.pb.h$right$$iwyu$\n", "dependency", StripProto(name), - "iwyu", (public_import) ? " // IWYU pragma: export" : ""); + "iwyu", (public_import) ? " // IWYU pragma: export" : "", + "left", well_known ? "<" : "\"", + "right", well_known ? ">" : "\""); } } diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index 09845458..fb46e387 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -54,6 +54,7 @@ namespace { static const char kAnyMessageName[] = "Any"; static const char kAnyProtoFile[] = "google/protobuf/any.proto"; +static const char kGoogleProtobufPrefix[] = "google/protobuf/"; string DotsToUnderscores(const string& name) { return StringReplace(name, ".", "_", true); @@ -600,6 +601,10 @@ bool IsAnyMessage(const Descriptor* descriptor) { descriptor->file()->name() == kAnyProtoFile; } +bool IsWellKnownMessage(const FileDescriptor* descriptor) { + return !descriptor->name().compare(0, 16, kGoogleProtobufPrefix); +} + enum Utf8CheckMode { STRICT = 0, // Parsing will fail if non UTF-8 data is in string fields. VERIFY = 1, // Only log an error but parsing will succeed. diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index 985cb04c..a22d414d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -265,6 +265,8 @@ inline bool SupportsArenas(const FieldDescriptor* field) { bool IsAnyMessage(const FileDescriptor* descriptor); bool IsAnyMessage(const Descriptor* descriptor); +bool IsWellKnownMessage(const FileDescriptor* descriptor); + void GenerateUtf8CheckCodeForString( const FieldDescriptor* field, bool for_parse, diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 8c0bfab7..af409c29 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -3364,7 +3364,7 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { } else { printer->Print( "output->WriteRaw(unknown_fields().data(),\n" - " unknown_fields().size());\n"); + " static_cast<int>(unknown_fields().size()));\n"); } } } diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 9c72043b..e0230a24 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -353,7 +353,7 @@ void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) { printer->Print( "public override string ToString() {\n" - " return pb::JsonFormatter.Default.Format(this);\n" + " return pb::JsonFormatter.ToDiagnosticString(this);\n" "}\n\n"); } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index 184a84a3..228c66f0 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -95,7 +95,7 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { // code is being compiled with. printer->Print( "#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != $protoc_gen_objc_version$\n" - "#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources.\n" + "#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.\n" "#endif\n" "\n", "protoc_gen_objc_version", diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index 266c2975..636673ae 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -2,7 +2,7 @@ // source: google/protobuf/compiler/plugin.proto #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION -#include "google/protobuf/compiler/plugin.pb.h" +#include <google/protobuf/compiler/plugin.pb.h> #include <algorithm> diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index ab79bdae..0a03e979 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -27,7 +27,7 @@ #include <google/protobuf/repeated_field.h> #include <google/protobuf/extension_set.h> #include <google/protobuf/unknown_field_set.h> -#include "google/protobuf/descriptor.pb.h" +#include <google/protobuf/descriptor.pb.h> // @@protoc_insertion_point(includes) namespace google { diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index ad53c03f..bc846609 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -2,7 +2,7 @@ // source: google/protobuf/descriptor.proto #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION -#include "google/protobuf/descriptor.pb.h" +#include <google/protobuf/descriptor.pb.h> #include <algorithm> diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc index 2e22ccb1..c7eed0d5 100644 --- a/src/google/protobuf/duration.pb.cc +++ b/src/google/protobuf/duration.pb.cc @@ -2,7 +2,7 @@ // source: google/protobuf/duration.proto #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION -#include "google/protobuf/duration.pb.h" +#include <google/protobuf/duration.pb.h> #include <algorithm> @@ -111,10 +111,10 @@ static void MergeFromFail(int line) { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int Duration::kSecondsFieldNumber; const int Duration::kNanosFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 Duration::Duration() : ::google::protobuf::Message(), _internal_metadata_(NULL) { diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc index 50cbd9a8..4a4f6eae 100644 --- a/src/google/protobuf/empty.pb.cc +++ b/src/google/protobuf/empty.pb.cc @@ -2,7 +2,7 @@ // source: google/protobuf/empty.proto #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION -#include "google/protobuf/empty.pb.h" +#include <google/protobuf/empty.pb.h> #include <algorithm> @@ -108,8 +108,8 @@ static void MergeFromFail(int line) { // =================================================================== -#ifndef _MSC_VER -#endif // !_MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 Empty::Empty() : ::google::protobuf::Message(), _internal_metadata_(NULL) { diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc index d8f4ee91..f834363b 100644 --- a/src/google/protobuf/field_mask.pb.cc +++ b/src/google/protobuf/field_mask.pb.cc @@ -2,7 +2,7 @@ // source: google/protobuf/field_mask.proto #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION -#include "google/protobuf/field_mask.pb.h" +#include <google/protobuf/field_mask.pb.h> #include <algorithm> @@ -110,9 +110,9 @@ static void MergeFromFail(int line) { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int FieldMask::kPathsFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 FieldMask::FieldMask() : ::google::protobuf::Message(), _internal_metadata_(NULL) { diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc index c8397639..1be3297e 100644 --- a/src/google/protobuf/source_context.pb.cc +++ b/src/google/protobuf/source_context.pb.cc @@ -2,7 +2,7 @@ // source: google/protobuf/source_context.proto #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION -#include "google/protobuf/source_context.pb.h" +#include <google/protobuf/source_context.pb.h> #include <algorithm> @@ -110,9 +110,9 @@ static void MergeFromFail(int line) { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int SourceContext::kFileNameFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 SourceContext::SourceContext() : ::google::protobuf::Message(), _internal_metadata_(NULL) { diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc index d5f89122..273645d9 100644 --- a/src/google/protobuf/struct.pb.cc +++ b/src/google/protobuf/struct.pb.cc @@ -2,7 +2,7 @@ // source: google/protobuf/struct.proto #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION -#include "google/protobuf/struct.pb.h" +#include <google/protobuf/struct.pb.h> #include <algorithm> @@ -212,9 +212,9 @@ static void MergeFromFail(int line) { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int Struct::kFieldsFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 Struct::Struct() : ::google::protobuf::Message(), _internal_metadata_(NULL) { @@ -480,14 +480,14 @@ Struct::mutable_fields() { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int Value::kNullValueFieldNumber; const int Value::kNumberValueFieldNumber; const int Value::kStringValueFieldNumber; const int Value::kBoolValueFieldNumber; const int Value::kStructValueFieldNumber; const int Value::kListValueFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 Value::Value() : ::google::protobuf::Message(), _internal_metadata_(NULL) { @@ -1218,9 +1218,9 @@ Value::KindCase Value::kind_case() const { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int ListValue::kValuesFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 ListValue::ListValue() : ::google::protobuf::Message(), _internal_metadata_(NULL) { diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc index 2ee0ec29..f0b09195 100644 --- a/src/google/protobuf/timestamp.pb.cc +++ b/src/google/protobuf/timestamp.pb.cc @@ -2,7 +2,7 @@ // source: google/protobuf/timestamp.proto #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION -#include "google/protobuf/timestamp.pb.h" +#include <google/protobuf/timestamp.pb.h> #include <algorithm> @@ -111,10 +111,10 @@ static void MergeFromFail(int line) { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int Timestamp::kSecondsFieldNumber; const int Timestamp::kNanosFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 Timestamp::Timestamp() : ::google::protobuf::Message(), _internal_metadata_(NULL) { diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc index 8f993561..5792dff2 100644 --- a/src/google/protobuf/type.pb.cc +++ b/src/google/protobuf/type.pb.cc @@ -2,7 +2,7 @@ // source: google/protobuf/type.proto #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION -#include "google/protobuf/type.pb.h" +#include <google/protobuf/type.pb.h> #include <algorithm> @@ -282,14 +282,14 @@ static void MergeFromFail(int line) { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int Type::kNameFieldNumber; const int Type::kFieldsFieldNumber; const int Type::kOneofsFieldNumber; const int Type::kOptionsFieldNumber; const int Type::kSourceContextFieldNumber; const int Type::kSyntaxFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 Type::Type() : ::google::protobuf::Message(), _internal_metadata_(NULL) { @@ -967,7 +967,7 @@ bool Field_Kind_IsValid(int value) { } } -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const Field_Kind Field::TYPE_UNKNOWN; const Field_Kind Field::TYPE_DOUBLE; const Field_Kind Field::TYPE_FLOAT; @@ -990,7 +990,7 @@ const Field_Kind Field::TYPE_SINT64; const Field_Kind Field::Kind_MIN; const Field_Kind Field::Kind_MAX; const int Field::Kind_ARRAYSIZE; -#endif // _MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 const ::google::protobuf::EnumDescriptor* Field_Cardinality_descriptor() { protobuf_AssignDescriptorsOnce(); return Field_Cardinality_descriptor_; @@ -1007,7 +1007,7 @@ bool Field_Cardinality_IsValid(int value) { } } -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const Field_Cardinality Field::CARDINALITY_UNKNOWN; const Field_Cardinality Field::CARDINALITY_OPTIONAL; const Field_Cardinality Field::CARDINALITY_REQUIRED; @@ -1015,8 +1015,8 @@ const Field_Cardinality Field::CARDINALITY_REPEATED; const Field_Cardinality Field::Cardinality_MIN; const Field_Cardinality Field::Cardinality_MAX; const int Field::Cardinality_ARRAYSIZE; -#endif // _MSC_VER -#ifndef _MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int Field::kKindFieldNumber; const int Field::kCardinalityFieldNumber; const int Field::kNumberFieldNumber; @@ -1026,7 +1026,7 @@ const int Field::kOneofIndexFieldNumber; const int Field::kPackedFieldNumber; const int Field::kOptionsFieldNumber; const int Field::kJsonNameFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 Field::Field() : ::google::protobuf::Message(), _internal_metadata_(NULL) { @@ -1830,13 +1830,13 @@ void Field::clear_json_name() { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int Enum::kNameFieldNumber; const int Enum::kEnumvalueFieldNumber; const int Enum::kOptionsFieldNumber; const int Enum::kSourceContextFieldNumber; const int Enum::kSyntaxFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 Enum::Enum() : ::google::protobuf::Message(), _internal_metadata_(NULL) { @@ -2379,11 +2379,11 @@ void Enum::clear_syntax() { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int EnumValue::kNameFieldNumber; const int EnumValue::kNumberFieldNumber; const int EnumValue::kOptionsFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 EnumValue::EnumValue() : ::google::protobuf::Message(), _internal_metadata_(NULL) { @@ -2775,10 +2775,10 @@ EnumValue::options() const { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int Option::kNameFieldNumber; const int Option::kValueFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 Option::Option() : ::google::protobuf::Message(), _internal_metadata_(NULL) { diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h index deda9213..2533eb4e 100644 --- a/src/google/protobuf/type.pb.h +++ b/src/google/protobuf/type.pb.h @@ -28,8 +28,8 @@ #include <google/protobuf/extension_set.h> #include <google/protobuf/generated_enum_reflection.h> #include <google/protobuf/unknown_field_set.h> -#include "google/protobuf/any.pb.h" -#include "google/protobuf/source_context.pb.h" +#include <google/protobuf/any.pb.h> +#include <google/protobuf/source_context.pb.h> // @@protoc_insertion_point(includes) namespace google { diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc index b2a7e970..e153687b 100644 --- a/src/google/protobuf/wrappers.pb.cc +++ b/src/google/protobuf/wrappers.pb.cc @@ -2,7 +2,7 @@ // source: google/protobuf/wrappers.proto #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION -#include "google/protobuf/wrappers.pb.h" +#include <google/protobuf/wrappers.pb.h> #include <algorithm> @@ -308,9 +308,9 @@ static void MergeFromFail(int line) { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int DoubleValue::kValueFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 DoubleValue::DoubleValue() : ::google::protobuf::Message(), _internal_metadata_(NULL) { @@ -532,9 +532,9 @@ void DoubleValue::clear_value() { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int FloatValue::kValueFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 FloatValue::FloatValue() : ::google::protobuf::Message(), _internal_metadata_(NULL) { @@ -756,9 +756,9 @@ void FloatValue::clear_value() { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int Int64Value::kValueFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 Int64Value::Int64Value() : ::google::protobuf::Message(), _internal_metadata_(NULL) { @@ -982,9 +982,9 @@ void Int64Value::clear_value() { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int UInt64Value::kValueFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 UInt64Value::UInt64Value() : ::google::protobuf::Message(), _internal_metadata_(NULL) { @@ -1208,9 +1208,9 @@ void UInt64Value::clear_value() { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int Int32Value::kValueFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 Int32Value::Int32Value() : ::google::protobuf::Message(), _internal_metadata_(NULL) { @@ -1434,9 +1434,9 @@ void Int32Value::clear_value() { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int UInt32Value::kValueFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 UInt32Value::UInt32Value() : ::google::protobuf::Message(), _internal_metadata_(NULL) { @@ -1660,9 +1660,9 @@ void UInt32Value::clear_value() { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int BoolValue::kValueFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 BoolValue::BoolValue() : ::google::protobuf::Message(), _internal_metadata_(NULL) { @@ -1884,9 +1884,9 @@ void BoolValue::clear_value() { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int StringValue::kValueFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 StringValue::StringValue() : ::google::protobuf::Message(), _internal_metadata_(NULL) { @@ -2155,9 +2155,9 @@ void StringValue::clear_value() { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int BytesValue::kValueFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 BytesValue::BytesValue() : ::google::protobuf::Message(), _internal_metadata_(NULL) { diff --git a/util/python/BUILD b/util/python/BUILD new file mode 100644 index 00000000..358c381c --- /dev/null +++ b/util/python/BUILD @@ -0,0 +1,8 @@ +# This is a placeholder for python headers. Projects needing to use +# fast cpp protos in protobuf's python interface should build with +# --define=use_fast_cpp_protos=true, and in addition, provide +# //util/python:python_headers dependency that in turn provides Python.h. +cc_library( + name = "python_headers", + visibility = ["//visibility:public"], +) |