aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml4
-rw-r--r--BUILD65
-rw-r--r--Makefile.am1
-rw-r--r--cmake/CMakeLists.txt2
-rw-r--r--conformance/Makefile.am19
-rwxr-xr-xconformance/conformance_python.py130
-rw-r--r--conformance/conformance_test.cc8
-rw-r--r--conformance/conformance_test_runner.cc6
-rw-r--r--conformance/failure_list_python.txt0
-rw-r--r--conformance/failure_list_python_cpp.txt25
-rw-r--r--csharp/src/AddressBook/Addressbook.cs9
-rw-r--r--csharp/src/Google.Protobuf.Conformance/Conformance.cs10
-rw-r--r--csharp/src/Google.Protobuf.Conformance/Program.cs43
-rw-r--r--csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs42
-rw-r--r--csharp/src/Google.Protobuf.Test/JsonParserTest.cs50
-rw-r--r--csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs14
-rw-r--r--csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs14
-rw-r--r--csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs2
-rw-r--r--csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs2
-rw-r--r--csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs20
-rw-r--r--csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs70
-rw-r--r--csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs8
-rw-r--r--csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs23
-rw-r--r--csharp/src/Google.Protobuf/Google.Protobuf.nuspec57
-rw-r--r--csharp/src/Google.Protobuf/JsonFormatter.cs170
-rw-r--r--csharp/src/Google.Protobuf/JsonParser.cs149
-rw-r--r--csharp/src/Google.Protobuf/JsonTokenizer.cs1046
-rw-r--r--csharp/src/Google.Protobuf/Reflection/Descriptor.cs44
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/Any.cs2
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/Api.cs6
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs2
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs2
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs2
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs2
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs6
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs2
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/Type.cs10
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs18
-rw-r--r--examples/addressbook.proto20
-rw-r--r--gmock.BUILD5
-rwxr-xr-xobjectivec/DevTools/full_mac_build.sh13
-rw-r--r--objectivec/GPBDictionary.m166
-rw-r--r--objectivec/GPBMessage.h2
-rw-r--r--objectivec/GPBMessage.m23
-rw-r--r--objectivec/GPBUtilities.h2
-rw-r--r--objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj8
-rw-r--r--objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme13
-rw-r--r--objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme13
-rw-r--r--objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj8
-rw-r--r--objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme13
-rw-r--r--objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme13
-rw-r--r--objectivec/README.md2
-rw-r--r--objectivec/Tests/GPBCodedInputStreamTests.m4
-rw-r--r--objectivec/Tests/GPBMessageTests+Serialization.m171
-rw-r--r--objectivec/Tests/GPBMessageTests.m16
-rw-r--r--objectivec/Tests/GPBSwiftTests.swift16
-rw-r--r--objectivec/Tests/UnitTests-Info.plist2
-rw-r--r--objectivec/Tests/iOSTestHarness/Info.plist2
-rw-r--r--objectivec/google/protobuf/Any.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/Api.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/Descriptor.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/Duration.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/Empty.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/FieldMask.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/SourceContext.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/Struct.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/Timestamp.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/Type.pbobjc.h2
-rw-r--r--objectivec/google/protobuf/Wrappers.pbobjc.h2
-rw-r--r--protobuf.bzl3
-rw-r--r--python/google/protobuf/pyext/extension_dict.h4
-rw-r--r--python/google/protobuf/pyext/message.h5
-rw-r--r--python/google/protobuf/pyext/message_map_container.h4
-rw-r--r--python/google/protobuf/pyext/repeated_composite_container.h4
-rw-r--r--python/google/protobuf/pyext/repeated_scalar_container.h4
-rw-r--r--python/google/protobuf/pyext/scalar_map_container.h4
-rwxr-xr-xpython/setup.py8
-rw-r--r--python/tox.ini2
-rw-r--r--six.BUILD1
-rw-r--r--src/google/protobuf/any.pb.cc6
-rw-r--r--src/google/protobuf/any.pb.h2
-rw-r--r--src/google/protobuf/api.pb.cc14
-rw-r--r--src/google/protobuf/api.pb.h4
-rw-r--r--src/google/protobuf/arena.h85
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc15
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc5
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h2
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message.cc2
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_file.cc2
-rw-r--r--src/google/protobuf/compiler/plugin.pb.cc2
-rw-r--r--src/google/protobuf/compiler/plugin.pb.h2
-rw-r--r--src/google/protobuf/descriptor.pb.cc2
-rw-r--r--src/google/protobuf/duration.pb.cc6
-rw-r--r--src/google/protobuf/empty.pb.cc6
-rw-r--r--src/google/protobuf/field_mask.pb.cc6
-rw-r--r--src/google/protobuf/source_context.pb.cc6
-rw-r--r--src/google/protobuf/struct.pb.cc14
-rw-r--r--src/google/protobuf/timestamp.pb.cc6
-rw-r--r--src/google/protobuf/type.pb.cc30
-rw-r--r--src/google/protobuf/type.pb.h4
-rw-r--r--src/google/protobuf/wrappers.pb.cc38
-rw-r--r--util/python/BUILD8
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
diff --git a/BUILD b/BUILD
index 97e3f45b..89b8162a 100644
--- a/BUILD
+++ b/BUILD
@@ -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
diff --git a/six.BUILD b/six.BUILD
index 55c53a42..fb0b3604 100644
--- a/six.BUILD
+++ b/six.BUILD
@@ -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"],
+)