aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--BUILD16
-rw-r--r--Makefile.am308
-rw-r--r--Protobuf.podspec2
-rw-r--r--README.md231
-rw-r--r--cmake/libprotoc.cmake1
-rw-r--r--conformance/Makefile.am4
-rw-r--r--conformance/failure_list_csharp.txt73
-rw-r--r--conformance/failure_list_python.txt92
-rw-r--r--conformance/failure_list_python_cpp.txt92
-rw-r--r--csharp/src/Google.Protobuf.Conformance/Program.cs27
-rw-r--r--csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs16
-rw-r--r--csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj2
-rw-r--r--csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs72
-rw-r--r--csharp/src/Google.Protobuf.Test/JsonParserTest.cs108
-rw-r--r--csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs45
-rw-r--r--csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs43
-rw-r--r--csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs38
-rw-r--r--csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs62
-rw-r--r--csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs31
-rw-r--r--csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs24
-rw-r--r--csharp/src/Google.Protobuf/Collections/RepeatedField.cs9
-rw-r--r--csharp/src/Google.Protobuf/FieldCodec.cs138
-rw-r--r--csharp/src/Google.Protobuf/Google.Protobuf.csproj2
-rw-r--r--csharp/src/Google.Protobuf/ICustomDiagnosticMessage.cs69
-rw-r--r--csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs11
-rw-r--r--csharp/src/Google.Protobuf/JsonFormatter.cs119
-rw-r--r--csharp/src/Google.Protobuf/JsonParser.cs90
-rw-r--r--csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs18
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs111
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs122
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs80
-rwxr-xr-xgenerate_descriptor_proto.sh39
-rw-r--r--java/core/src/main/java/com/google/protobuf/BoundedByteString.java124
-rw-r--r--java/core/src/main/java/com/google/protobuf/ByteString.java364
-rw-r--r--java/core/src/main/java/com/google/protobuf/CodedInputStream.java52
-rw-r--r--java/core/src/main/java/com/google/protobuf/ExperimentalApi.java36
-rw-r--r--java/core/src/main/java/com/google/protobuf/GeneratedMessage.java60
-rw-r--r--java/core/src/main/java/com/google/protobuf/Internal.java30
-rw-r--r--java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java12
-rw-r--r--java/core/src/main/java/com/google/protobuf/LiteralByteString.java267
-rw-r--r--java/core/src/main/java/com/google/protobuf/MapFieldLite.java2
-rw-r--r--java/core/src/main/java/com/google/protobuf/Parser.java12
-rw-r--r--java/core/src/main/java/com/google/protobuf/RopeByteString.java6
-rw-r--r--java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java (renamed from java/core/src/main/java/com/google/protobuf/UnsafeByteStrings.java)16
-rw-r--r--java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java4
-rw-r--r--java/core/src/test/java/com/google/protobuf/ByteStringTest.java8
-rw-r--r--java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java18
-rw-r--r--java/core/src/test/java/com/google/protobuf/NioByteStringTest.java17
-rw-r--r--java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java211
-rw-r--r--java/lite/pom.xml4
-rw-r--r--m4/acx_check_suncc.m417
-rw-r--r--objectivec/google/protobuf/Descriptor.pbobjc.h52
-rw-r--r--objectivec/google/protobuf/Descriptor.pbobjc.m149
-rw-r--r--python/google/protobuf/internal/json_format_test.py244
-rw-r--r--python/google/protobuf/internal/well_known_types.py102
-rw-r--r--python/google/protobuf/internal/well_known_types_test.py123
-rw-r--r--python/google/protobuf/json_format.py214
-rw-r--r--python/google/protobuf/pyext/map_container.cc2
-rw-r--r--src/Makefile.am3
-rw-r--r--src/README.md209
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc5
-rw-r--r--src/google/protobuf/compiler/cpp/metadata_test.cc58
-rw-r--r--src/google/protobuf/compiler/java/java_extension_lite.cc0
-rw-r--r--src/google/protobuf/compiler/java/java_extension_lite.h0
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc17
-rw-r--r--src/google/protobuf/compiler/java/java_message_builder.cc2
-rw-r--r--src/google/protobuf/descriptor.pb.cc969
-rw-r--r--src/google/protobuf/descriptor.pb.h409
-rw-r--r--src/google/protobuf/descriptor.proto28
-rw-r--r--src/google/protobuf/repeated_field.h2
-rw-r--r--src/google/protobuf/stubs/atomicops.h2
-rw-r--r--src/google/protobuf/stubs/platform_macros.h2
-rw-r--r--src/google/protobuf/stubs/statusor.h4
-rw-r--r--src/google/protobuf/unittest_well_known_types.proto2
-rw-r--r--src/google/protobuf/util/internal/testdata/maps.proto29
76 files changed, 4536 insertions, 1447 deletions
diff --git a/.gitignore b/.gitignore
index 19e52129..a2d6ca9c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,6 +58,7 @@ python/.eggs/
python/.tox
python/build/
python/google/protobuf/compiler/
+python/google/protobuf/util/
src/protoc
src/unittest_proto_middleman
diff --git a/BUILD b/BUILD
index 8022098c..3cac4a86 100644
--- a/BUILD
+++ b/BUILD
@@ -459,19 +459,23 @@ cc_test(
# Java support
################################################################################
genrule(
- name = "generate_java_descriptor_proto",
- srcs = ["src/google/protobuf/descriptor.proto"],
- outs = ["com/google/protobuf/DescriptorProtos.java"],
- cmd = "$(location :protoc) --java_out=$(@D)/../../.. $<",
+ name = "gen_well_known_protos_java",
+ srcs = WELL_KNOWN_PROTOS,
+ outs = [
+ "wellknown.srcjar"
+ ],
+ cmd = "$(location :protoc) --java_out=$(@D)/wellknown.jar" +
+ " -Isrc $(SRCS) " +
+ " && mv $(@D)/wellknown.jar $(@D)/wellknown.srcjar",
tools = [":protoc"],
)
java_library(
name = "protobuf_java",
srcs = glob([
- "java/src/main/java/com/google/protobuf/*.java",
+ "java/core/src/main/java/com/google/protobuf/*.java",
]) + [
- ":generate_java_descriptor_proto",
+ ":gen_well_known_protos_java",
],
visibility = ["//visibility:public"],
)
diff --git a/Makefile.am b/Makefile.am
index 3d39a898..188346fe 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -181,160 +181,160 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf/packages.config \
csharp/src/packages/repositories.config
-java_EXTRA_DIST= \
- java/src/main/java/com/google/protobuf/AbstractMessage.java \
- java/src/main/java/com/google/protobuf/AbstractMessageLite.java \
- java/src/main/java/com/google/protobuf/AbstractParser.java \
- java/src/main/java/com/google/protobuf/AbstractProtobufList.java \
- java/src/main/java/com/google/protobuf/BlockingRpcChannel.java \
- java/src/main/java/com/google/protobuf/BlockingService.java \
- java/src/main/java/com/google/protobuf/BooleanArrayList.java \
- java/src/main/java/com/google/protobuf/BoundedByteString.java \
- java/src/main/java/com/google/protobuf/ByteString.java \
- java/src/main/java/com/google/protobuf/CodedInputStream.java \
- java/src/main/java/com/google/protobuf/CodedOutputStream.java \
- java/src/main/java/com/google/protobuf/Descriptors.java \
- java/src/main/java/com/google/protobuf/DoubleArrayList.java \
- java/src/main/java/com/google/protobuf/DynamicMessage.java \
- java/src/main/java/com/google/protobuf/Extension.java \
- java/src/main/java/com/google/protobuf/ExtensionLite.java \
- java/src/main/java/com/google/protobuf/ExtensionRegistry.java \
- java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java \
- java/src/main/java/com/google/protobuf/FieldSet.java \
- java/src/main/java/com/google/protobuf/FloatArrayList.java \
- java/src/main/java/com/google/protobuf/GeneratedMessage.java \
- java/src/main/java/com/google/protobuf/GeneratedMessageLite.java \
- java/src/main/java/com/google/protobuf/IntArrayList.java \
- java/src/main/java/com/google/protobuf/Internal.java \
- java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
- java/src/main/java/com/google/protobuf/LazyField.java \
- java/src/main/java/com/google/protobuf/LazyFieldLite.java \
- java/src/main/java/com/google/protobuf/LazyStringArrayList.java \
- java/src/main/java/com/google/protobuf/LazyStringList.java \
- java/src/main/java/com/google/protobuf/LiteralByteString.java \
- java/src/main/java/com/google/protobuf/LongArrayList.java \
- java/src/main/java/com/google/protobuf/MapEntry.java \
- java/src/main/java/com/google/protobuf/MapEntryLite.java \
- java/src/main/java/com/google/protobuf/MapField.java \
- java/src/main/java/com/google/protobuf/MapFieldLite.java \
- java/src/main/java/com/google/protobuf/Message.java \
- java/src/main/java/com/google/protobuf/MessageLite.java \
- java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java \
- java/src/main/java/com/google/protobuf/MessageLiteToString.java \
- java/src/main/java/com/google/protobuf/MessageLiteToString.java \
- java/src/main/java/com/google/protobuf/MessageOrBuilder.java \
- java/src/main/java/com/google/protobuf/MessageReflection.java \
- java/src/main/java/com/google/protobuf/MutabilityOracle.java \
- java/src/main/java/com/google/protobuf/NioByteString.java \
- java/src/main/java/com/google/protobuf/Parser.java \
- java/src/main/java/com/google/protobuf/ProtobufArrayList.java \
- java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java \
- java/src/main/java/com/google/protobuf/ProtocolStringList.java \
- java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java \
- java/src/main/java/com/google/protobuf/RopeByteString.java \
- java/src/main/java/com/google/protobuf/RpcCallback.java \
- java/src/main/java/com/google/protobuf/RpcChannel.java \
- java/src/main/java/com/google/protobuf/RpcController.java \
- java/src/main/java/com/google/protobuf/RpcUtil.java \
- java/src/main/java/com/google/protobuf/Service.java \
- java/src/main/java/com/google/protobuf/ServiceException.java \
- java/src/main/java/com/google/protobuf/SingleFieldBuilder.java \
- java/src/main/java/com/google/protobuf/SmallSortedMap.java \
- java/src/main/java/com/google/protobuf/TextFormat.java \
- java/src/main/java/com/google/protobuf/TextFormatEscaper.java \
- java/src/main/java/com/google/protobuf/TextFormatEscaper.java \
- java/src/main/java/com/google/protobuf/UninitializedMessageException.java \
- java/src/main/java/com/google/protobuf/UnknownFieldSet.java \
- java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java \
- java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java \
- java/src/main/java/com/google/protobuf/UnsafeByteStrings.java \
- java/src/main/java/com/google/protobuf/Utf8.java \
- java/src/main/java/com/google/protobuf/WireFormat.java \
- java/src/test/java/com/google/protobuf/AbstractMessageTest.java \
- java/src/test/java/com/google/protobuf/AnyTest.java \
- java/src/test/java/com/google/protobuf/BooleanArrayListTest.java \
- java/src/test/java/com/google/protobuf/BoundedByteStringTest.java \
- java/src/test/java/com/google/protobuf/ByteStringTest.java \
- java/src/test/java/com/google/protobuf/CheckUtf8Test.java \
- java/src/test/java/com/google/protobuf/CodedInputStreamTest.java \
- java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java \
- java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java \
- java/src/test/java/com/google/protobuf/DescriptorsTest.java \
- java/src/test/java/com/google/protobuf/DoubleArrayListTest.java \
- java/src/test/java/com/google/protobuf/DynamicMessageTest.java \
- java/src/test/java/com/google/protobuf/FieldPresenceTest.java \
- java/src/test/java/com/google/protobuf/FloatArrayListTest.java \
- java/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java \
- java/src/test/java/com/google/protobuf/GeneratedMessageTest.java \
- java/src/test/java/com/google/protobuf/IntArrayListTest.java \
- java/src/test/java/com/google/protobuf/IsValidUtf8Test.java \
- java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java \
- java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java \
- java/src/test/java/com/google/protobuf/LazyFieldTest.java \
- java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java \
- java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java \
- java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java \
- java/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java \
- java/src/test/java/com/google/protobuf/LiteTest.java \
- java/src/test/java/com/google/protobuf/LiteralByteStringTest.java \
- java/src/test/java/com/google/protobuf/LongArrayListTest.java \
- java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java \
- java/src/test/java/com/google/protobuf/MapForProto2Test.java \
- java/src/test/java/com/google/protobuf/MapTest.java \
- java/src/test/java/com/google/protobuf/MessageTest.java \
- java/src/test/java/com/google/protobuf/NestedBuildersTest.java \
- java/src/test/java/com/google/protobuf/NioByteStringTest.java \
- java/src/test/java/com/google/protobuf/ParserTest.java \
- java/src/test/java/com/google/protobuf/ProtobufArrayListTest.java \
- java/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java \
- java/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java \
- java/src/test/java/com/google/protobuf/RopeByteStringTest.java \
- java/src/test/java/com/google/protobuf/ServiceTest.java \
- java/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java \
- java/src/test/java/com/google/protobuf/SmallSortedMapTest.java \
- java/src/test/java/com/google/protobuf/TestBadIdentifiers.java \
- java/src/test/java/com/google/protobuf/TestUtil.java \
- java/src/test/java/com/google/protobuf/TextFormatTest.java \
- java/src/test/java/com/google/protobuf/UnknownEnumValueTest.java \
- java/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java \
- java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java \
- java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java \
- java/src/test/java/com/google/protobuf/WellKnownTypesTest.java \
- java/src/test/java/com/google/protobuf/WireFormatTest.java \
- java/src/test/java/com/google/protobuf/any_test.proto \
- java/src/test/java/com/google/protobuf/field_presence_test.proto \
- java/src/test/java/com/google/protobuf/lazy_fields_lite.proto \
- java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto \
- java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto \
- java/src/test/java/com/google/protobuf/map_for_proto2_test.proto \
- java/src/test/java/com/google/protobuf/map_initialization_order_test.proto \
- java/src/test/java/com/google/protobuf/map_test.proto \
- java/src/test/java/com/google/protobuf/multiple_files_test.proto \
- java/src/test/java/com/google/protobuf/nested_builders_test.proto \
- java/src/test/java/com/google/protobuf/nested_extension.proto \
- java/src/test/java/com/google/protobuf/nested_extension_lite.proto \
- java/src/test/java/com/google/protobuf/non_nested_extension.proto \
- java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto \
- java/src/test/java/com/google/protobuf/outer_class_name_test.proto \
- java/src/test/java/com/google/protobuf/outer_class_name_test2.proto \
- java/src/test/java/com/google/protobuf/outer_class_name_test3.proto \
- java/src/test/java/com/google/protobuf/test_bad_identifiers.proto \
- java/src/test/java/com/google/protobuf/test_check_utf8.proto \
- java/src/test/java/com/google/protobuf/test_check_utf8_size.proto \
- java/src/test/java/com/google/protobuf/test_custom_options.proto \
- java/src/test/java/com/google/protobuf/test_extra_interfaces.proto \
- java/util/pom.xml \
- java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java \
- java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java \
- java/util/src/main/java/com/google/protobuf/util/JsonFormat.java \
- java/util/src/main/java/com/google/protobuf/util/TimeUtil.java \
- java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java \
- java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java \
- java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java \
- java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java \
- java/util/src/test/java/com/google/protobuf/util/json_test.proto \
- java/pom.xml \
- java/README.md
+java_EXTRA_DIST= \
+ java/README.md \
+ java/core/generate-sources-build.xml \
+ java/core/generate-test-sources-build.xml \
+ java/core/pom.xml \
+ java/core/src/main/java/com/google/protobuf/AbstractMessage.java \
+ java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java \
+ java/core/src/main/java/com/google/protobuf/AbstractParser.java \
+ java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java \
+ java/core/src/main/java/com/google/protobuf/BlockingRpcChannel.java \
+ java/core/src/main/java/com/google/protobuf/BlockingService.java \
+ java/core/src/main/java/com/google/protobuf/BooleanArrayList.java \
+ java/core/src/main/java/com/google/protobuf/ByteString.java \
+ java/core/src/main/java/com/google/protobuf/CodedInputStream.java \
+ java/core/src/main/java/com/google/protobuf/CodedOutputStream.java \
+ java/core/src/main/java/com/google/protobuf/Descriptors.java \
+ java/core/src/main/java/com/google/protobuf/DoubleArrayList.java \
+ java/core/src/main/java/com/google/protobuf/DynamicMessage.java \
+ java/core/src/main/java/com/google/protobuf/Extension.java \
+ java/core/src/main/java/com/google/protobuf/ExtensionLite.java \
+ java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java \
+ java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java \
+ java/core/src/main/java/com/google/protobuf/FieldSet.java \
+ java/core/src/main/java/com/google/protobuf/FloatArrayList.java \
+ java/core/src/main/java/com/google/protobuf/GeneratedMessage.java \
+ java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java \
+ java/core/src/main/java/com/google/protobuf/IntArrayList.java \
+ java/core/src/main/java/com/google/protobuf/Internal.java \
+ java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
+ java/core/src/main/java/com/google/protobuf/LazyField.java \
+ java/core/src/main/java/com/google/protobuf/LazyFieldLite.java \
+ java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java \
+ java/core/src/main/java/com/google/protobuf/LazyStringList.java \
+ java/core/src/main/java/com/google/protobuf/LongArrayList.java \
+ java/core/src/main/java/com/google/protobuf/MapEntry.java \
+ java/core/src/main/java/com/google/protobuf/MapEntryLite.java \
+ java/core/src/main/java/com/google/protobuf/MapField.java \
+ java/core/src/main/java/com/google/protobuf/MapFieldLite.java \
+ java/core/src/main/java/com/google/protobuf/Message.java \
+ java/core/src/main/java/com/google/protobuf/MessageLite.java \
+ java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java \
+ java/core/src/main/java/com/google/protobuf/MessageLiteToString.java \
+ java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java \
+ java/core/src/main/java/com/google/protobuf/MessageReflection.java \
+ java/core/src/main/java/com/google/protobuf/MutabilityOracle.java \
+ java/core/src/main/java/com/google/protobuf/NioByteString.java \
+ java/core/src/main/java/com/google/protobuf/Parser.java \
+ java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java \
+ java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java \
+ java/core/src/main/java/com/google/protobuf/ProtocolStringList.java \
+ java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java \
+ java/core/src/main/java/com/google/protobuf/RopeByteString.java \
+ java/core/src/main/java/com/google/protobuf/RpcCallback.java \
+ java/core/src/main/java/com/google/protobuf/RpcChannel.java \
+ java/core/src/main/java/com/google/protobuf/RpcController.java \
+ java/core/src/main/java/com/google/protobuf/RpcUtil.java \
+ java/core/src/main/java/com/google/protobuf/Service.java \
+ java/core/src/main/java/com/google/protobuf/ServiceException.java \
+ java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java \
+ java/core/src/main/java/com/google/protobuf/SmallSortedMap.java \
+ java/core/src/main/java/com/google/protobuf/TextFormat.java \
+ java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java \
+ java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java \
+ java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java \
+ java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java \
+ java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java \
+ java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java \
+ java/core/src/main/java/com/google/protobuf/Utf8.java \
+ java/core/src/main/java/com/google/protobuf/WireFormat.java \
+ java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java \
+ java/core/src/test/java/com/google/protobuf/AnyTest.java \
+ java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java \
+ java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java \
+ java/core/src/test/java/com/google/protobuf/ByteStringTest.java \
+ java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java \
+ java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java \
+ java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java \
+ java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java \
+ java/core/src/test/java/com/google/protobuf/DescriptorsTest.java \
+ java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java \
+ java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java \
+ java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java \
+ java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java \
+ java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java \
+ java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java \
+ java/core/src/test/java/com/google/protobuf/IntArrayListTest.java \
+ java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java \
+ java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java \
+ java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java \
+ java/core/src/test/java/com/google/protobuf/LazyFieldTest.java \
+ java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java \
+ java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java \
+ java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java \
+ java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java \
+ java/core/src/test/java/com/google/protobuf/LiteTest.java \
+ java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java \
+ java/core/src/test/java/com/google/protobuf/LongArrayListTest.java \
+ java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java \
+ java/core/src/test/java/com/google/protobuf/MapForProto2Test.java \
+ java/core/src/test/java/com/google/protobuf/MapTest.java \
+ java/core/src/test/java/com/google/protobuf/MessageTest.java \
+ java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java \
+ java/core/src/test/java/com/google/protobuf/NioByteStringTest.java \
+ java/core/src/test/java/com/google/protobuf/ParserTest.java \
+ java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java \
+ java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java \
+ java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java \
+ java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java \
+ java/core/src/test/java/com/google/protobuf/ServiceTest.java \
+ java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java \
+ java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java \
+ java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java \
+ java/core/src/test/java/com/google/protobuf/TestUtil.java \
+ java/core/src/test/java/com/google/protobuf/TextFormatTest.java \
+ java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java \
+ java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java \
+ java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java \
+ java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java \
+ java/core/src/test/java/com/google/protobuf/WellKnownTypesTest.java \
+ java/core/src/test/java/com/google/protobuf/WireFormatTest.java \
+ java/core/src/test/proto/com/google/protobuf/any_test.proto \
+ java/core/src/test/proto/com/google/protobuf/field_presence_test.proto \
+ java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto \
+ java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto \
+ java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto \
+ java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto \
+ java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto \
+ java/core/src/test/proto/com/google/protobuf/map_test.proto \
+ java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto \
+ java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto \
+ java/core/src/test/proto/com/google/protobuf/nested_extension.proto \
+ java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto \
+ java/core/src/test/proto/com/google/protobuf/non_nested_extension.proto \
+ java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto \
+ java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto \
+ java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto \
+ java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto \
+ java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto \
+ java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto \
+ java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto \
+ java/core/src/test/proto/com/google/protobuf/test_custom_options.proto \
+ java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto \
+ java/lite/pom.xml \
+ java/pom.xml \
+ java/util/pom.xml \
+ java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java \
+ java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java \
+ java/util/src/main/java/com/google/protobuf/util/JsonFormat.java \
+ java/util/src/main/java/com/google/protobuf/util/TimeUtil.java \
+ java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java \
+ java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java \
+ java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java \
+ java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java \
+ java/util/src/test/proto/com/google/protobuf/util/json_test.proto
javanano_EXTRA_DIST= \
javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java \
diff --git a/Protobuf.podspec b/Protobuf.podspec
index 92ff2904..73a60222 100644
--- a/Protobuf.podspec
+++ b/Protobuf.podspec
@@ -5,7 +5,7 @@
# dependent projects use the :git notation to refer to the library.
Pod::Spec.new do |s|
s.name = 'Protobuf'
- s.version = '3.0.0-alpha-4.1'
+ s.version = '3.0.0-beta-2'
s.summary = 'Protocol Buffers v.3 runtime library for Objective-C.'
s.homepage = 'https://github.com/google/protobuf'
s.license = 'New BSD'
diff --git a/README.md b/README.md
index 19723d36..070d579b 100644
--- a/README.md
+++ b/README.md
@@ -7,207 +7,66 @@ Copyright 2008 Google Inc.
https://developers.google.com/protocol-buffers/
-C++ Installation - Unix
------------------------
+Overview
+--------
-To build protobuf from source, the following tools are needed:
+Protocol Buffers (a.k.a., protobuf) are Google's language-neutral,
+platform-neutral, extensible mechanism for serializing structured data. You
+can find [protobuf's documentaion on the Google Developers site](https://developers.google.com/protocol-buffers/).
- * autoconf
- * automake
- * libtool
- * curl (used to download gmock)
+This README file contains protobuf installation instructions. To install
+protobuf, you need to install the protocol compiler (used to compile .proto
+files) and the protobuf runtime for your chosen programming language.
-On Ubuntu, you can install them with:
+Protocol Compiler Installation
+------------------------------
- $ sudo apt-get install autoconf automake libtool curl
+The protocol compiler is written in C++. If you are using C++, please follow
+the [C++ Installation Instructions](src/README.md) to install protoc along
+with the C++ runtime.
-On other platforms, please use the corresponding package managing tool to
-install them before proceeding.
+For non-C++ users, the simplest way to install the protocol compiler is to
+download a pre-built binary from our release page:
-If you get the source from github, you need to generate the configure script
-first:
+ [https://github.com/google/protobuf/releases](https://github.com/google/protobuf/releases)
- $ ./autogen.sh
+In the downloads section of each release, you can find pre-built binaries in
+zip packages: protoc-$VERSION-$PLATFORM.zip. It contains the protoc binary
+as well as a set of standard .proto files distributed along with protobuf.
-This will download gmock source (which is used for C++ Protocol Buffer
-unit-tests) to the current directory and run automake, autoconf, etc.
-to generate the configure script and various template makefiles.
+If you are looking for an old version that is not available in the release
+page, check out the maven repo here:
-You can skip this step if you are using a release package (which already
-contains gmock and the configure script).
+ [http://repo1.maven.org/maven2/com/google/protobuf/protoc/](http://repo1.maven.org/maven2/com/google/protobuf/protoc/)
-To build and install the C++ Protocol Buffer runtime and the Protocol
-Buffer compiler (protoc) execute the following:
+These pre-built binaries are only provided for released versions. If you want
+to use the github master version at HEAD, or you need to modify protobuf code,
+or you are using C++, it's recommended to build your own protoc binary from
+source.
- $ ./configure
- $ make
- $ make check
- $ sudo make install
- $ sudo ldconfig # refresh shared library cache.
+If you would like to build protoc binary from source, see the [C++ Installaton
+Instructions](src/README.md).
-If "make check" fails, you can still install, but it is likely that
-some features of this library will not work correctly on your system.
-Proceed at your own risk.
+Protobuf Runtime Installation
+-----------------------------
-For advanced usage information on configure and make, please refer to the
-autoconf documentation:
+Protobuf supports several different programming languages. For each programming
+language, you can find instructions in the corresponding source directory about
+how to install protobuf runtime for that specific language:
- http://www.gnu.org/software/autoconf/manual/autoconf.html#Running-configure-Scripts
+| Language | Source |
+|--------------------------------------|-------------------------------------------------------|
+| C++ (include C++ runtime and protoc) | [src](src) |
+| Java | [java](java) |
+| Python | [python](python) |
+| Objective-C | [objectivec](objectivec) |
+| C# | [csharp](csharp) |
+| JavaNano | [javanano](javanano) |
+| JavaScript | [js](js) |
+| Ruby | [ruby](ruby) |
+| Go | [golang/protobuf](https://github.com/golang/protobuf) |
+| PHP | TBD |
-**Hint on install location**
-
- By default, the package will be installed to /usr/local. However,
- on many platforms, /usr/local/lib is not part of LD_LIBRARY_PATH.
- You can add it, but it may be easier to just install to /usr
- instead. To do this, invoke configure as follows:
-
- ./configure --prefix=/usr
-
- If you already built the package with a different prefix, make sure
- to run "make clean" before building again.
-
-**Compiling dependent packages**
-
- To compile a package that uses Protocol Buffers, you need to pass
- various flags to your compiler and linker. As of version 2.2.0,
- Protocol Buffers integrates with pkg-config to manage this. If you
- have pkg-config installed, then you can invoke it to get a list of
- flags like so:
-
- pkg-config --cflags protobuf # print compiler flags
- pkg-config --libs protobuf # print linker flags
- pkg-config --cflags --libs protobuf # print both
-
- For example:
-
- c++ my_program.cc my_proto.pb.cc `pkg-config --cflags --libs protobuf`
-
- Note that packages written prior to the 2.2.0 release of Protocol
- Buffers may not yet integrate with pkg-config to get flags, and may
- not pass the correct set of flags to correctly link against
- libprotobuf. If the package in question uses autoconf, you can
- often fix the problem by invoking its configure script like:
-
- configure CXXFLAGS="$(pkg-config --cflags protobuf)" \
- LIBS="$(pkg-config --libs protobuf)"
-
- This will force it to use the correct flags.
-
- If you are writing an autoconf-based package that uses Protocol
- Buffers, you should probably use the PKG_CHECK_MODULES macro in your
- configure script like:
-
- PKG_CHECK_MODULES([protobuf], [protobuf])
-
- See the pkg-config man page for more info.
-
- If you only want protobuf-lite, substitute "protobuf-lite" in place
- of "protobuf" in these examples.
-
-**Note for Mac users**
-
- For a Mac system, Unix tools are not available by default. You will first need
- to install Xcode from the Mac AppStore and then run the following command from
- a terminal:
-
- $ sudo xcode-select --install
-
- To install Unix tools, you can install "port" following the instructions at
- https://www.macports.org . This will reside in /opt/local/bin/port for most
- Mac installations.
-
- $ sudo /opt/local/bin/port install autoconf automake libtool
-
- Then follow the Unix instructions above.
-
-**Note for cross-compiling**
-
- The makefiles normally invoke the protoc executable that they just
- built in order to build tests. When cross-compiling, the protoc
- executable may not be executable on the host machine. In this case,
- you must build a copy of protoc for the host machine first, then use
- the --with-protoc option to tell configure to use it instead. For
- example:
-
- ./configure --with-protoc=protoc
-
- This will use the installed protoc (found in your $PATH) instead of
- trying to execute the one built during the build process. You can
- also use an executable that hasn't been installed. For example, if
- you built the protobuf package for your host machine in ../host,
- you might do:
-
- ./configure --with-protoc=../host/src/protoc
-
- Either way, you must make sure that the protoc executable you use
- has the same version as the protobuf source code you are trying to
- use it with.
-
-**Note for Solaris users**
-
- Solaris 10 x86 has a bug that will make linking fail, complaining
- about libstdc++.la being invalid. We have included a work-around
- in this package. To use the work-around, run configure as follows:
-
- ./configure LDFLAGS=-L$PWD/src/solaris
-
- See src/solaris/libstdc++.la for more info on this bug.
-
-**Note for HP C++ Tru64 users**
-
- To compile invoke configure as follows:
-
- ./configure CXXFLAGS="-O -std ansi -ieee -D__USE_STD_IOSTREAM"
-
- Also, you will need to use gmake instead of make.
-
-**Note for AIX users**
-
- Compile using the IBM xlC C++ compiler as follows:
-
- ./configure CXX=xlC
-
- Also, you will need to use GNU `make` (`gmake`) instead of AIX `make`.
-
-C++ Installation - Windows
---------------------------
-
-If you only need the protoc binary, you can download it from the release
-page:
-
- https://github.com/google/protobuf/releases
-
-In the downloads section, download the zip file protoc-$VERSION-win32.zip.
-It contains the protoc binary as well as public proto files of protobuf
-library.
-
-To build from source using Microsoft Visual C++, see cmake/README.md.
-
-To build from source using Cygwin or MinGW, follow the Unix installation
-instructions, above.
-
-Binary Compatibility Warning
-----------------------------
-
-Due to the nature of C++, it is unlikely that any two versions of the
-Protocol Buffers C++ runtime libraries will have compatible ABIs.
-That is, if you linked an executable against an older version of
-libprotobuf, it is unlikely to work with a newer version without
-re-compiling. This problem, when it occurs, will normally be detected
-immediately on startup of your app. Still, you may want to consider
-using static linkage. You can configure this package to install
-static libraries only using:
-
- ./configure --disable-shared
-
-Java and Python Installation
-----------------------------
-
-The Java and Python runtime libraries for Protocol Buffers are located
-in the java and python directories. See the README file in each
-directory for more information on how to compile and install them.
-Note that both of them require you to first install the Protocol
-Buffer compiler (protoc), which is part of the C++ package.
Usage
-----
diff --git a/cmake/libprotoc.cmake b/cmake/libprotoc.cmake
index e70e453e..8df8986a 100644
--- a/cmake/libprotoc.cmake
+++ b/cmake/libprotoc.cmake
@@ -37,6 +37,7 @@ set(libprotoc_files
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum_field_lite.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum_lite.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_extension.cc
+ ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_extension_lite.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_field.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_file.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_generator.cc
diff --git a/conformance/Makefile.am b/conformance/Makefile.am
index 9703101a..2a43113b 100644
--- a/conformance/Makefile.am
+++ b/conformance/Makefile.am
@@ -114,13 +114,13 @@ MAINTAINERCLEANFILES = \
Makefile.in
javac_middleman: ConformanceJava.java protoc_middleman $(other_language_protoc_outputs)
- jar=`ls ../java/util/target/*.jar` && javac -classpath ../java/target/classes:$$jar ConformanceJava.java com/google/protobuf/conformance/Conformance.java
+ jar=`ls ../java/util/target/*jar-with-dependencies.jar` && javac -classpath ../java/target/classes:$$jar ConformanceJava.java com/google/protobuf/conformance/Conformance.java
@touch javac_middleman
conformance-java: javac_middleman
@echo "Writing shortcut script conformance-java..."
@echo '#! /bin/sh' > conformance-java
- @jar=`ls ../java/util/target/*.jar` && echo java -classpath .:../java/target/classes:$$jar ConformanceJava '$$@' >> conformance-java
+ @jar=`ls ../java/util/target/*jar-with-dependencies.jar` && echo java -classpath .:../java/target/classes:$$jar ConformanceJava '$$@' >> conformance-java
@chmod +x conformance-java
# Currently the conformance code is alongside the rest of the C#
diff --git a/conformance/failure_list_csharp.txt b/conformance/failure_list_csharp.txt
index feb17689..a46cee47 100644
--- a/conformance/failure_list_csharp.txt
+++ b/conformance/failure_list_csharp.txt
@@ -1,89 +1,16 @@
-DurationProtoInputTooLarge.JsonOutput
-DurationProtoInputTooSmall.JsonOutput
-FieldMaskNumbersDontRoundTrip.JsonOutput
-FieldMaskPathsDontRoundTrip.JsonOutput
-FieldMaskTooManyUnderscore.JsonOutput
JsonInput.AnyWithValueForInteger.JsonOutput
JsonInput.AnyWithValueForJsonObject.JsonOutput
-JsonInput.BoolFieldAllCapitalFalse
-JsonInput.BoolFieldAllCapitalTrue
-JsonInput.BoolFieldCamelCaseFalse
-JsonInput.BoolFieldCamelCaseTrue
-JsonInput.BoolMapFieldKeyNotQuoted
-JsonInput.BytesFieldInvalidBase64Characters
-JsonInput.BytesFieldNoPadding
-JsonInput.DoubleFieldInfinityNotQuoted
-JsonInput.DoubleFieldNanNotQuoted
-JsonInput.DoubleFieldNegativeInfinityNotQuoted
-JsonInput.DoubleFieldTooLarge
-JsonInput.DoubleFieldTooSmall
-JsonInput.DurationHas3FractionalDigits.Validator
-JsonInput.DurationHas6FractionalDigits.Validator
-JsonInput.DurationHas9FractionalDigits.Validator
-JsonInput.DurationMaxValue.JsonOutput
-JsonInput.DurationMaxValue.ProtobufOutput
-JsonInput.DurationMinValue.JsonOutput
-JsonInput.DurationMinValue.ProtobufOutput
-JsonInput.EnumFieldNotQuoted
-JsonInput.EnumFieldNumericValueNonZero.JsonOutput
-JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
-JsonInput.EnumFieldNumericValueZero.JsonOutput
-JsonInput.EnumFieldNumericValueZero.ProtobufOutput
-JsonInput.EnumFieldUnknownValue.Validator
-JsonInput.FieldMaskInvalidCharacter
-JsonInput.FieldNameDuplicate
-JsonInput.FieldNameDuplicateDifferentCasing2
JsonInput.FieldNameInLowerCamelCase.Validator
JsonInput.FieldNameInSnakeCase.JsonOutput
JsonInput.FieldNameInSnakeCase.ProtobufOutput
-JsonInput.FieldNameNotQuoted
JsonInput.FieldNameWithMixedCases.JsonOutput
JsonInput.FieldNameWithMixedCases.ProtobufOutput
JsonInput.FieldNameWithMixedCases.Validator
-JsonInput.FloatFieldInfinityNotQuoted
-JsonInput.FloatFieldNanNotQuoted
-JsonInput.FloatFieldNegativeInfinityNotQuoted
-JsonInput.Int32FieldLeadingZero
JsonInput.Int32FieldMinFloatValue.JsonOutput
JsonInput.Int32FieldMinValue.JsonOutput
-JsonInput.Int32FieldNegativeWithLeadingZero
-JsonInput.Int32FieldPlusSign
-JsonInput.Int32MapFieldKeyNotQuoted
JsonInput.Int64FieldMaxValueNotQuoted.JsonOutput
JsonInput.Int64FieldMaxValueNotQuoted.ProtobufOutput
-JsonInput.Int64MapFieldKeyNotQuoted
-JsonInput.JsonWithComments
-JsonInput.MapFieldKeyIsNull
-JsonInput.MapFieldValueIsNull
-JsonInput.OneofFieldDuplicate
JsonInput.OriginalProtoFieldName.JsonOutput
-JsonInput.OriginalProtoFieldName.ProtobufOutput
-JsonInput.RepeatedBoolWrapper.ProtobufOutput
-JsonInput.RepeatedDoubleWrapper.ProtobufOutput
-JsonInput.RepeatedFieldMessageElementIsNull
-JsonInput.RepeatedFieldPrimitiveElementIsNull
-JsonInput.RepeatedFieldTrailingComma
-JsonInput.RepeatedFloatWrapper.ProtobufOutput
-JsonInput.RepeatedInt32Wrapper.ProtobufOutput
-JsonInput.RepeatedInt64Wrapper.ProtobufOutput
-JsonInput.RepeatedUint32Wrapper.ProtobufOutput
-JsonInput.RepeatedUint64Wrapper.ProtobufOutput
-JsonInput.StringFieldInvalidEscape
-JsonInput.StringFieldSurrogateInWrongOrder
JsonInput.StringFieldSurrogatePair.JsonOutput
-JsonInput.StringFieldUnpairedHighSurrogate
-JsonInput.StringFieldUnpairedLowSurrogate
-JsonInput.StringFieldUnterminatedEscape
-JsonInput.StringFieldUppercaseEscapeLetter
-JsonInput.TimestampHas3FractionalDigits.Validator
-JsonInput.TimestampHas6FractionalDigits.Validator
-JsonInput.TimestampHas9FractionalDigits.Validator
-JsonInput.TrailingCommaInAnObject
-JsonInput.Uint32MapFieldKeyNotQuoted
JsonInput.Uint64FieldMaxValueNotQuoted.JsonOutput
JsonInput.Uint64FieldMaxValueNotQuoted.ProtobufOutput
-JsonInput.Uint64MapFieldKeyNotQuoted
-JsonInput.ValueAcceptNull.JsonOutput
-JsonInput.ValueAcceptNull.ProtobufOutput
-TimestampProtoInputTooLarge.JsonOutput
-TimestampProtoInputTooSmall.JsonOutput
diff --git a/conformance/failure_list_python.txt b/conformance/failure_list_python.txt
index c9934598..d2e52637 100644
--- a/conformance/failure_list_python.txt
+++ b/conformance/failure_list_python.txt
@@ -3,11 +3,10 @@ DurationProtoInputTooSmall.JsonOutput
FieldMaskNumbersDontRoundTrip.JsonOutput
FieldMaskPathsDontRoundTrip.JsonOutput
FieldMaskTooManyUnderscore.JsonOutput
-JsonInput.AllFieldAcceptNull.JsonOutput
JsonInput.Any.JsonOutput
+JsonInput.Any.ProtobufOutput
JsonInput.AnyNested.JsonOutput
JsonInput.AnyNested.ProtobufOutput
-JsonInput.Any.ProtobufOutput
JsonInput.AnyUnorderedTypeTag.JsonOutput
JsonInput.AnyUnorderedTypeTag.ProtobufOutput
JsonInput.AnyWithDuration.JsonOutput
@@ -24,132 +23,50 @@ JsonInput.AnyWithValueForInteger.JsonOutput
JsonInput.AnyWithValueForInteger.ProtobufOutput
JsonInput.AnyWithValueForJsonObject.JsonOutput
JsonInput.AnyWithValueForJsonObject.ProtobufOutput
-JsonInput.BoolFieldFalse.JsonOutput
-JsonInput.BoolFieldTrue.JsonOutput
-JsonInput.BoolMapEscapedKey.JsonOutput
-JsonInput.BoolMapField.JsonOutput
JsonInput.BytesFieldInvalidBase64Characters
-JsonInput.BytesField.JsonOutput
-JsonInput.BytesRepeatedField.JsonOutput
-JsonInput.DoubleFieldInfinity.JsonOutput
JsonInput.DoubleFieldInfinityNotQuoted
-JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
-JsonInput.DoubleFieldMaxPositiveValue.JsonOutput
-JsonInput.DoubleFieldMinNegativeValue.JsonOutput
-JsonInput.DoubleFieldMinPositiveValue.JsonOutput
-JsonInput.DoubleFieldNan.JsonOutput
JsonInput.DoubleFieldNanNotQuoted
-JsonInput.DoubleFieldNegativeInfinity.JsonOutput
JsonInput.DoubleFieldNegativeInfinityNotQuoted
-JsonInput.DoubleFieldQuotedValue.JsonOutput
JsonInput.DoubleFieldTooSmall
JsonInput.DurationJsonInputTooLarge
JsonInput.DurationJsonInputTooSmall
-JsonInput.DurationMaxValue.JsonOutput
-JsonInput.DurationMinValue.JsonOutput
JsonInput.DurationMissingS
-JsonInput.DurationRepeatedValue.JsonOutput
-JsonInput.EnumField.JsonOutput
JsonInput.EnumFieldNumericValueNonZero.JsonOutput
JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
JsonInput.EnumFieldNumericValueZero.JsonOutput
JsonInput.EnumFieldNumericValueZero.ProtobufOutput
JsonInput.EnumFieldUnknownValue.Validator
-JsonInput.EnumRepeatedField.JsonOutput
-JsonInput.FieldMaskInvalidCharacter
-JsonInput.FieldMask.JsonOutput
JsonInput.FieldMask.ProtobufOutput
-JsonInput.FieldNameEscaped.JsonOutput
+JsonInput.FieldMaskInvalidCharacter
JsonInput.FieldNameInLowerCamelCase.Validator
JsonInput.FieldNameInSnakeCase.JsonOutput
JsonInput.FieldNameInSnakeCase.ProtobufOutput
-JsonInput.FieldNameWithMixedCases.JsonOutput
-JsonInput.FieldNameWithNumbers.JsonOutput
-JsonInput.FloatFieldInfinity.JsonOutput
JsonInput.FloatFieldInfinityNotQuoted
-JsonInput.FloatFieldMaxNegativeValue.JsonOutput
-JsonInput.FloatFieldMaxPositiveValue.JsonOutput
-JsonInput.FloatFieldMinNegativeValue.JsonOutput
-JsonInput.FloatFieldMinPositiveValue.JsonOutput
-JsonInput.FloatFieldNan.JsonOutput
JsonInput.FloatFieldNanNotQuoted
-JsonInput.FloatFieldNegativeInfinity.JsonOutput
JsonInput.FloatFieldNegativeInfinityNotQuoted
-JsonInput.FloatFieldQuotedValue.JsonOutput
JsonInput.FloatFieldTooLarge
JsonInput.FloatFieldTooSmall
-JsonInput.HelloWorld.JsonOutput
JsonInput.Int32FieldExponentialFormat.JsonOutput
JsonInput.Int32FieldExponentialFormat.ProtobufOutput
JsonInput.Int32FieldFloatTrailingZero.JsonOutput
JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
JsonInput.Int32FieldMaxFloatValue.JsonOutput
JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
-JsonInput.Int32FieldMaxValue.JsonOutput
JsonInput.Int32FieldMinFloatValue.JsonOutput
JsonInput.Int32FieldMinFloatValue.ProtobufOutput
JsonInput.Int32FieldMinValue.JsonOutput
-JsonInput.Int32FieldStringValueEscaped.JsonOutput
-JsonInput.Int32FieldStringValue.JsonOutput
-JsonInput.Int32MapEscapedKey.JsonOutput
-JsonInput.Int32MapField.JsonOutput
-JsonInput.Int64FieldMaxValue.JsonOutput
-JsonInput.Int64FieldMaxValueNotQuoted.JsonOutput
-JsonInput.Int64FieldMinValue.JsonOutput
-JsonInput.Int64FieldMinValueNotQuoted.JsonOutput
-JsonInput.Int64MapEscapedKey.JsonOutput
-JsonInput.Int64MapField.JsonOutput
-JsonInput.MessageField.JsonOutput
-JsonInput.MessageMapField.JsonOutput
-JsonInput.MessageRepeatedField.JsonOutput
-JsonInput.OptionalBoolWrapper.JsonOutput
-JsonInput.OptionalBytesWrapper.JsonOutput
-JsonInput.OptionalDoubleWrapper.JsonOutput
-JsonInput.OptionalFloatWrapper.JsonOutput
-JsonInput.OptionalInt32Wrapper.JsonOutput
-JsonInput.OptionalInt64Wrapper.JsonOutput
-JsonInput.OptionalStringWrapper.JsonOutput
-JsonInput.OptionalUint32Wrapper.JsonOutput
-JsonInput.OptionalUint64Wrapper.JsonOutput
-JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
JsonInput.OriginalProtoFieldName.JsonOutput
JsonInput.OriginalProtoFieldName.ProtobufOutput
-JsonInput.PrimitiveRepeatedField.JsonOutput
-JsonInput.RepeatedBoolWrapper.JsonOutput
-JsonInput.RepeatedBytesWrapper.JsonOutput
-JsonInput.RepeatedDoubleWrapper.JsonOutput
JsonInput.RepeatedFieldMessageElementIsNull
JsonInput.RepeatedFieldPrimitiveElementIsNull
JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
-JsonInput.RepeatedFloatWrapper.JsonOutput
-JsonInput.RepeatedInt32Wrapper.JsonOutput
-JsonInput.RepeatedInt64Wrapper.JsonOutput
-JsonInput.RepeatedStringWrapper.JsonOutput
-JsonInput.RepeatedUint32Wrapper.JsonOutput
-JsonInput.RepeatedUint64Wrapper.JsonOutput
-JsonInput.StringFieldEscape.JsonOutput
-JsonInput.StringField.JsonOutput
JsonInput.StringFieldSurrogatePair.JsonOutput
-JsonInput.StringFieldUnicodeEscape.JsonOutput
-JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.JsonOutput
-JsonInput.StringFieldUnicode.JsonOutput
JsonInput.StringFieldUnpairedLowSurrogate
-JsonInput.StringRepeatedField.JsonOutput
JsonInput.Struct.JsonOutput
JsonInput.Struct.ProtobufOutput
JsonInput.TimestampJsonInputLowercaseT
-JsonInput.TimestampMaxValue.JsonOutput
-JsonInput.TimestampMinValue.JsonOutput
-JsonInput.TimestampRepeatedValue.JsonOutput
-JsonInput.TimestampWithNegativeOffset.JsonOutput
-JsonInput.TimestampWithPositiveOffset.JsonOutput
JsonInput.Uint32FieldMaxFloatValue.JsonOutput
JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
-JsonInput.Uint32FieldMaxValue.JsonOutput
-JsonInput.Uint32MapField.JsonOutput
-JsonInput.Uint64FieldMaxValue.JsonOutput
-JsonInput.Uint64FieldMaxValueNotQuoted.JsonOutput
-JsonInput.Uint64MapField.JsonOutput
JsonInput.ValueAcceptBool.JsonOutput
JsonInput.ValueAcceptBool.ProtobufOutput
JsonInput.ValueAcceptFloat.JsonOutput
@@ -164,10 +81,5 @@ JsonInput.ValueAcceptObject.JsonOutput
JsonInput.ValueAcceptObject.ProtobufOutput
JsonInput.ValueAcceptString.JsonOutput
JsonInput.ValueAcceptString.ProtobufOutput
-JsonInput.WrapperTypesWithNullValue.JsonOutput
-ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
-ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
-ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
-ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
TimestampProtoInputTooLarge.JsonOutput
TimestampProtoInputTooSmall.JsonOutput
diff --git a/conformance/failure_list_python_cpp.txt b/conformance/failure_list_python_cpp.txt
index 9c710e99..7b5e45f9 100644
--- a/conformance/failure_list_python_cpp.txt
+++ b/conformance/failure_list_python_cpp.txt
@@ -12,11 +12,10 @@ DurationProtoInputTooSmall.JsonOutput
FieldMaskNumbersDontRoundTrip.JsonOutput
FieldMaskPathsDontRoundTrip.JsonOutput
FieldMaskTooManyUnderscore.JsonOutput
-JsonInput.AllFieldAcceptNull.JsonOutput
JsonInput.Any.JsonOutput
+JsonInput.Any.ProtobufOutput
JsonInput.AnyNested.JsonOutput
JsonInput.AnyNested.ProtobufOutput
-JsonInput.Any.ProtobufOutput
JsonInput.AnyUnorderedTypeTag.JsonOutput
JsonInput.AnyUnorderedTypeTag.ProtobufOutput
JsonInput.AnyWithDuration.JsonOutput
@@ -33,132 +32,50 @@ JsonInput.AnyWithValueForInteger.JsonOutput
JsonInput.AnyWithValueForInteger.ProtobufOutput
JsonInput.AnyWithValueForJsonObject.JsonOutput
JsonInput.AnyWithValueForJsonObject.ProtobufOutput
-JsonInput.BoolFieldFalse.JsonOutput
-JsonInput.BoolFieldTrue.JsonOutput
-JsonInput.BoolMapEscapedKey.JsonOutput
-JsonInput.BoolMapField.JsonOutput
JsonInput.BytesFieldInvalidBase64Characters
-JsonInput.BytesField.JsonOutput
-JsonInput.BytesRepeatedField.JsonOutput
-JsonInput.DoubleFieldInfinity.JsonOutput
JsonInput.DoubleFieldInfinityNotQuoted
-JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
-JsonInput.DoubleFieldMaxPositiveValue.JsonOutput
-JsonInput.DoubleFieldMinNegativeValue.JsonOutput
-JsonInput.DoubleFieldMinPositiveValue.JsonOutput
-JsonInput.DoubleFieldNan.JsonOutput
JsonInput.DoubleFieldNanNotQuoted
-JsonInput.DoubleFieldNegativeInfinity.JsonOutput
JsonInput.DoubleFieldNegativeInfinityNotQuoted
-JsonInput.DoubleFieldQuotedValue.JsonOutput
JsonInput.DoubleFieldTooSmall
JsonInput.DurationJsonInputTooLarge
JsonInput.DurationJsonInputTooSmall
-JsonInput.DurationMaxValue.JsonOutput
-JsonInput.DurationMinValue.JsonOutput
JsonInput.DurationMissingS
-JsonInput.DurationRepeatedValue.JsonOutput
-JsonInput.EnumField.JsonOutput
JsonInput.EnumFieldNumericValueNonZero.JsonOutput
JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
JsonInput.EnumFieldNumericValueZero.JsonOutput
JsonInput.EnumFieldNumericValueZero.ProtobufOutput
JsonInput.EnumFieldUnknownValue.Validator
-JsonInput.EnumRepeatedField.JsonOutput
-JsonInput.FieldMaskInvalidCharacter
-JsonInput.FieldMask.JsonOutput
JsonInput.FieldMask.ProtobufOutput
-JsonInput.FieldNameEscaped.JsonOutput
+JsonInput.FieldMaskInvalidCharacter
JsonInput.FieldNameInLowerCamelCase.Validator
JsonInput.FieldNameInSnakeCase.JsonOutput
JsonInput.FieldNameInSnakeCase.ProtobufOutput
-JsonInput.FieldNameWithMixedCases.JsonOutput
-JsonInput.FieldNameWithNumbers.JsonOutput
-JsonInput.FloatFieldInfinity.JsonOutput
JsonInput.FloatFieldInfinityNotQuoted
-JsonInput.FloatFieldMaxNegativeValue.JsonOutput
-JsonInput.FloatFieldMaxPositiveValue.JsonOutput
-JsonInput.FloatFieldMinNegativeValue.JsonOutput
-JsonInput.FloatFieldMinPositiveValue.JsonOutput
-JsonInput.FloatFieldNan.JsonOutput
JsonInput.FloatFieldNanNotQuoted
-JsonInput.FloatFieldNegativeInfinity.JsonOutput
JsonInput.FloatFieldNegativeInfinityNotQuoted
-JsonInput.FloatFieldQuotedValue.JsonOutput
JsonInput.FloatFieldTooLarge
JsonInput.FloatFieldTooSmall
-JsonInput.HelloWorld.JsonOutput
JsonInput.Int32FieldExponentialFormat.JsonOutput
JsonInput.Int32FieldExponentialFormat.ProtobufOutput
JsonInput.Int32FieldFloatTrailingZero.JsonOutput
JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
JsonInput.Int32FieldMaxFloatValue.JsonOutput
JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
-JsonInput.Int32FieldMaxValue.JsonOutput
JsonInput.Int32FieldMinFloatValue.JsonOutput
JsonInput.Int32FieldMinFloatValue.ProtobufOutput
JsonInput.Int32FieldMinValue.JsonOutput
-JsonInput.Int32FieldStringValueEscaped.JsonOutput
-JsonInput.Int32FieldStringValue.JsonOutput
-JsonInput.Int32MapEscapedKey.JsonOutput
-JsonInput.Int32MapField.JsonOutput
-JsonInput.Int64FieldMaxValue.JsonOutput
-JsonInput.Int64FieldMaxValueNotQuoted.JsonOutput
-JsonInput.Int64FieldMinValue.JsonOutput
-JsonInput.Int64FieldMinValueNotQuoted.JsonOutput
-JsonInput.Int64MapEscapedKey.JsonOutput
-JsonInput.Int64MapField.JsonOutput
-JsonInput.MessageField.JsonOutput
-JsonInput.MessageMapField.JsonOutput
-JsonInput.MessageRepeatedField.JsonOutput
-JsonInput.OptionalBoolWrapper.JsonOutput
-JsonInput.OptionalBytesWrapper.JsonOutput
-JsonInput.OptionalDoubleWrapper.JsonOutput
-JsonInput.OptionalFloatWrapper.JsonOutput
-JsonInput.OptionalInt32Wrapper.JsonOutput
-JsonInput.OptionalInt64Wrapper.JsonOutput
-JsonInput.OptionalStringWrapper.JsonOutput
-JsonInput.OptionalUint32Wrapper.JsonOutput
-JsonInput.OptionalUint64Wrapper.JsonOutput
-JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
JsonInput.OriginalProtoFieldName.JsonOutput
JsonInput.OriginalProtoFieldName.ProtobufOutput
-JsonInput.PrimitiveRepeatedField.JsonOutput
-JsonInput.RepeatedBoolWrapper.JsonOutput
-JsonInput.RepeatedBytesWrapper.JsonOutput
-JsonInput.RepeatedDoubleWrapper.JsonOutput
JsonInput.RepeatedFieldMessageElementIsNull
JsonInput.RepeatedFieldPrimitiveElementIsNull
JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
-JsonInput.RepeatedFloatWrapper.JsonOutput
-JsonInput.RepeatedInt32Wrapper.JsonOutput
-JsonInput.RepeatedInt64Wrapper.JsonOutput
-JsonInput.RepeatedStringWrapper.JsonOutput
-JsonInput.RepeatedUint32Wrapper.JsonOutput
-JsonInput.RepeatedUint64Wrapper.JsonOutput
-JsonInput.StringFieldEscape.JsonOutput
-JsonInput.StringField.JsonOutput
JsonInput.StringFieldSurrogatePair.JsonOutput
-JsonInput.StringFieldUnicodeEscape.JsonOutput
-JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.JsonOutput
-JsonInput.StringFieldUnicode.JsonOutput
JsonInput.StringFieldUnpairedLowSurrogate
-JsonInput.StringRepeatedField.JsonOutput
JsonInput.Struct.JsonOutput
JsonInput.Struct.ProtobufOutput
JsonInput.TimestampJsonInputLowercaseT
-JsonInput.TimestampMaxValue.JsonOutput
-JsonInput.TimestampMinValue.JsonOutput
-JsonInput.TimestampRepeatedValue.JsonOutput
-JsonInput.TimestampWithNegativeOffset.JsonOutput
-JsonInput.TimestampWithPositiveOffset.JsonOutput
JsonInput.Uint32FieldMaxFloatValue.JsonOutput
JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
-JsonInput.Uint32FieldMaxValue.JsonOutput
-JsonInput.Uint32MapField.JsonOutput
-JsonInput.Uint64FieldMaxValue.JsonOutput
-JsonInput.Uint64FieldMaxValueNotQuoted.JsonOutput
-JsonInput.Uint64MapField.JsonOutput
JsonInput.ValueAcceptBool.JsonOutput
JsonInput.ValueAcceptBool.ProtobufOutput
JsonInput.ValueAcceptFloat.JsonOutput
@@ -173,11 +90,6 @@ JsonInput.ValueAcceptObject.JsonOutput
JsonInput.ValueAcceptObject.ProtobufOutput
JsonInput.ValueAcceptString.JsonOutput
JsonInput.ValueAcceptString.ProtobufOutput
-JsonInput.WrapperTypesWithNullValue.JsonOutput
-ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
-ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
-ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
-ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
ProtobufInput.PrematureEofInPackedField.BOOL
diff --git a/csharp/src/Google.Protobuf.Conformance/Program.cs b/csharp/src/Google.Protobuf.Conformance/Program.cs
index 8f72c8f9..f3f7e295 100644
--- a/csharp/src/Google.Protobuf.Conformance/Program.cs
+++ b/csharp/src/Google.Protobuf.Conformance/Program.cs
@@ -101,15 +101,26 @@ namespace Google.Protobuf.Conformance
{
return new ConformanceResponse { ParseError = e.Message };
}
- switch (request.RequestedOutputFormat)
+ catch (InvalidJsonException e)
{
- case global::Conformance.WireFormat.JSON:
- 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:
- throw new Exception("Unsupported request output format: " + request.PayloadCase);
+ return new ConformanceResponse { ParseError = e.Message };
+ }
+ try
+ {
+ switch (request.RequestedOutputFormat)
+ {
+ case global::Conformance.WireFormat.JSON:
+ 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:
+ throw new Exception("Unsupported request output format: " + request.PayloadCase);
+ }
+ }
+ catch (InvalidOperationException e)
+ {
+ return new ConformanceResponse { SerializeError = e.Message };
}
}
diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
index cda7f885..14cc6d19 100644
--- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
+++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
@@ -695,5 +695,21 @@ namespace Google.Protobuf
var parsed = TestAllTypes.Parser.ParseFrom(stream);
Assert.AreEqual(new TestAllTypes { SingleFixed32 = 123 }, parsed);
}
+
+ [Test]
+ public void CustomDiagnosticMessage_DirectToStringCall()
+ {
+ var message = new ForeignMessage { C = 31 };
+ Assert.AreEqual("{ \"c\": 31, \"@cInHex\": \"1f\" }", message.ToString());
+ Assert.AreEqual("{ \"c\": 31 }", JsonFormatter.Default.Format(message));
+ }
+
+ [Test]
+ public void CustomDiagnosticMessage_Nested()
+ {
+ var message = new TestAllTypes { SingleForeignMessage = new ForeignMessage { C = 16 } };
+ Assert.AreEqual("{ \"singleForeignMessage\": { \"c\": 16, \"@cInHex\": \"10\" } }", message.ToString());
+ Assert.AreEqual("{ \"singleForeignMessage\": { \"c\": 16 } }", JsonFormatter.Default.Format(message));
+ }
}
}
diff --git a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
index 903454eb..20ae8e48 100644
--- a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
+++ b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
@@ -102,6 +102,7 @@
<Compile Include="Reflection\TypeRegistryTest.cs" />
<Compile Include="SampleEnum.cs" />
<Compile Include="SampleMessages.cs" />
+ <Compile Include="TestProtos\ForeignMessagePartial.cs" />
<Compile Include="TestProtos\MapUnittestProto3.cs" />
<Compile Include="TestProtos\UnittestImportProto3.cs" />
<Compile Include="TestProtos\UnittestImportPublicProto3.cs" />
@@ -114,6 +115,7 @@
<Compile Include="TestProtos\UnittestWellKnownTypes.cs" />
<Compile Include="WellKnownTypes\AnyTest.cs" />
<Compile Include="WellKnownTypes\DurationTest.cs" />
+ <Compile Include="WellKnownTypes\FieldMaskTest.cs" />
<Compile Include="WellKnownTypes\TimestampTest.cs" />
<Compile Include="WellKnownTypes\WrappersTest.cs" />
</ItemGroup>
diff --git a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
index ace70b00..42455043 100644
--- a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
+++ b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
@@ -165,34 +165,31 @@ namespace Google.Protobuf
}
[Test]
- public void UnknownEnumValueOmitted_SingleField()
+ public void UnknownEnumValueNumeric_SingleField()
{
var message = new TestAllTypes { SingleForeignEnum = (ForeignEnum) 100 };
- AssertJson("{ }", JsonFormatter.Default.Format(message));
+ AssertJson("{ 'singleForeignEnum': 100 }", JsonFormatter.Default.Format(message));
}
[Test]
- public void UnknownEnumValueOmitted_RepeatedField()
+ public void UnknownEnumValueNumeric_RepeatedField()
{
var message = new TestAllTypes { RepeatedForeignEnum = { ForeignEnum.FOREIGN_BAZ, (ForeignEnum) 100, ForeignEnum.FOREIGN_FOO } };
- AssertJson("{ 'repeatedForeignEnum': [ 'FOREIGN_BAZ', 'FOREIGN_FOO' ] }", JsonFormatter.Default.Format(message));
+ AssertJson("{ 'repeatedForeignEnum': [ 'FOREIGN_BAZ', 100, 'FOREIGN_FOO' ] }", JsonFormatter.Default.Format(message));
}
[Test]
- public void UnknownEnumValueOmitted_MapField()
+ public void UnknownEnumValueNumeric_MapField()
{
- // This matches the C++ behaviour.
var message = new TestMap { MapInt32Enum = { { 1, MapEnum.MAP_ENUM_FOO }, { 2, (MapEnum) 100 }, { 3, MapEnum.MAP_ENUM_BAR } } };
- AssertJson("{ 'mapInt32Enum': { '1': 'MAP_ENUM_FOO', '3': 'MAP_ENUM_BAR' } }", JsonFormatter.Default.Format(message));
+ AssertJson("{ 'mapInt32Enum': { '1': 'MAP_ENUM_FOO', '2': 100, '3': 'MAP_ENUM_BAR' } }", JsonFormatter.Default.Format(message));
}
[Test]
- public void UnknownEnumValueOmitted_RepeatedField_AllEntriesUnknown()
+ public void UnknownEnumValue_RepeatedField_AllEntriesUnknown()
{
- // *Maybe* we should hold off on writing the "[" until we find that we've got at least one value to write...
- // but this is what happens at the moment, and it doesn't seem too awful.
var message = new TestAllTypes { RepeatedForeignEnum = { (ForeignEnum) 200, (ForeignEnum) 100 } };
- AssertJson("{ 'repeatedForeignEnum': [ ] }", JsonFormatter.Default.Format(message));
+ AssertJson("{ 'repeatedForeignEnum': [ 200, 100 ] }", JsonFormatter.Default.Format(message));
}
[Test]
@@ -315,6 +312,15 @@ namespace Google.Protobuf
[Test]
[TestCase("1970-01-01T00:00:00Z", 0)]
+ [TestCase("1970-01-01T00:00:00.000000001Z", 1)]
+ [TestCase("1970-01-01T00:00:00.000000010Z", 10)]
+ [TestCase("1970-01-01T00:00:00.000000100Z", 100)]
+ [TestCase("1970-01-01T00:00:00.000001Z", 1000)]
+ [TestCase("1970-01-01T00:00:00.000010Z", 10000)]
+ [TestCase("1970-01-01T00:00:00.000100Z", 100000)]
+ [TestCase("1970-01-01T00:00:00.001Z", 1000000)]
+ [TestCase("1970-01-01T00:00:00.010Z", 10000000)]
+ [TestCase("1970-01-01T00:00:00.100Z", 100000000)]
[TestCase("1970-01-01T00:00:00.100Z", 100000000)]
[TestCase("1970-01-01T00:00:00.120Z", 120000000)]
[TestCase("1970-01-01T00:00:00.123Z", 123000000)]
@@ -340,6 +346,17 @@ namespace Google.Protobuf
}
[Test]
+ [TestCase(-1, -1)] // Would be valid as duration
+ [TestCase(1, Timestamp.MaxNanos + 1)]
+ [TestCase(Timestamp.UnixSecondsAtBclMaxValue + 1, 0)]
+ [TestCase(Timestamp.UnixSecondsAtBclMinValue - 1, 0)]
+ public void TimestampStandalone_NonNormalized(long seconds, int nanoseconds)
+ {
+ var timestamp = new Timestamp { Seconds = seconds, Nanos = nanoseconds };
+ Assert.Throws<InvalidOperationException>(() => JsonFormatter.Default.Format(timestamp));
+ }
+
+ [Test]
public void TimestampField()
{
var message = new TestWellKnownTypes { TimestampField = new Timestamp() };
@@ -350,6 +367,14 @@ namespace Google.Protobuf
[TestCase(0, 0, "0s")]
[TestCase(1, 0, "1s")]
[TestCase(-1, 0, "-1s")]
+ [TestCase(0, 1, "0.000000001s")]
+ [TestCase(0, 10, "0.000000010s")]
+ [TestCase(0, 100, "0.000000100s")]
+ [TestCase(0, 1000, "0.000001s")]
+ [TestCase(0, 10000, "0.000010s")]
+ [TestCase(0, 100000, "0.000100s")]
+ [TestCase(0, 1000000, "0.001s")]
+ [TestCase(0, 10000000, "0.010s")]
[TestCase(0, 100000000, "0.100s")]
[TestCase(0, 120000000, "0.120s")]
[TestCase(0, 123000000, "0.123s")]
@@ -362,12 +387,19 @@ namespace Google.Protobuf
[TestCase(0, -100000000, "-0.100s")]
[TestCase(1, 100000000, "1.100s")]
[TestCase(-1, -100000000, "-1.100s")]
- // Non-normalized examples
- [TestCase(1, 2123456789, "3.123456789s")]
- [TestCase(1, -100000000, "0.900s")]
public void DurationStandalone(long seconds, int nanoseconds, string expected)
{
- Assert.AreEqual(WrapInQuotes(expected), new Duration { Seconds = seconds, Nanos = nanoseconds }.ToString());
+ var json = JsonFormatter.Default.Format(new Duration { Seconds = seconds, Nanos = nanoseconds });
+ Assert.AreEqual(WrapInQuotes(expected), json);
+ }
+
+ [Test]
+ [TestCase(1, 2123456789)]
+ [TestCase(1, -100000000)]
+ public void DurationStandalone_NonNormalized(long seconds, int nanoseconds)
+ {
+ var duration = new Duration { Seconds = seconds, Nanos = nanoseconds };
+ Assert.Throws<InvalidOperationException>(() => JsonFormatter.Default.Format(duration));
}
[Test]
@@ -396,6 +428,16 @@ namespace Google.Protobuf
}
[Test]
+ [TestCase("foo__bar")]
+ [TestCase("foo_3_ar")]
+ [TestCase("fooBar")]
+ public void FieldMaskInvalid(string input)
+ {
+ var mask = new FieldMask { Paths = { input } };
+ Assert.Throws<InvalidOperationException>(() => JsonFormatter.Default.Format(mask));
+ }
+
+ [Test]
public void FieldMaskStandalone()
{
var fieldMask = new FieldMask { Paths = { "", "single", "with_underscore", "nested.field.name", "nested..double_dot" } };
diff --git a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
index 303baacc..d21da58a 100644
--- a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
+++ b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
@@ -72,6 +72,14 @@ namespace Google.Protobuf
}
[Test]
+ public void OriginalFieldNameAccepted()
+ {
+ var json = "{ \"single_int32\": 10 }";
+ var expected = new TestAllTypes { SingleInt32 = 10 };
+ Assert.AreEqual(expected, TestAllTypes.Parser.ParseJson(json));
+ }
+
+ [Test]
public void SourceContextRoundtrip()
{
AssertRoundtrip(new SourceContext { FileName = "foo.proto" });
@@ -116,7 +124,9 @@ namespace Google.Protobuf
[Test]
public void SingularWrappers_ExplicitNulls()
{
- var message = new TestWellKnownTypes();
+ // When we parse the "valueField": null part, we remember it... basically, it's one case
+ // where explicit default values don't fully roundtrip.
+ var message = new TestWellKnownTypes { ValueField = Value.ForNull() };
var json = new JsonFormatter(new JsonFormatter.Settings(true)).Format(message);
var parsed = JsonParser.Default.Parse<TestWellKnownTypes>(json);
Assert.AreEqual(message, parsed);
@@ -143,6 +153,14 @@ namespace Google.Protobuf
}
[Test]
+ public void ExplicitNullValue()
+ {
+ string json = "{\"valueField\": null}";
+ var message = JsonParser.Default.Parse<TestWellKnownTypes>(json);
+ Assert.AreEqual(new TestWellKnownTypes { ValueField = Value.ForNull() }, message);
+ }
+
+ [Test]
public void BytesWrapper_Standalone()
{
ByteString data = ByteString.CopyFrom(1, 2, 3);
@@ -171,6 +189,36 @@ namespace Google.Protobuf
}
[Test]
+ public void RepeatedField_NullElementProhibited()
+ {
+ string json = "{ \"repeated_foreign_message\": [null] }";
+ Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+ }
+
+ [Test]
+ public void RepeatedField_NullOverallValueAllowed()
+ {
+ string json = "{ \"repeated_foreign_message\": null }";
+ Assert.AreEqual(new TestAllTypes(), TestAllTypes.Parser.ParseJson(json));
+ }
+
+ [Test]
+ [TestCase("{ \"mapInt32Int32\": { \"10\": null }")]
+ [TestCase("{ \"mapStringString\": { \"abc\": null }")]
+ [TestCase("{ \"mapInt32ForeignMessage\": { \"10\": null }")]
+ public void MapField_NullValueProhibited(string json)
+ {
+ Assert.Throws<InvalidProtocolBufferException>(() => TestMap.Parser.ParseJson(json));
+ }
+
+ [Test]
+ public void MapField_NullOverallValueAllowed()
+ {
+ string json = "{ \"mapInt32Int32\": null }";
+ Assert.AreEqual(new TestMap(), TestMap.Parser.ParseJson(json));
+ }
+
+ [Test]
public void IndividualWrapperTypes()
{
Assert.AreEqual(new StringValue { Value = "foo" }, StringValue.Parser.ParseJson("\"foo\""));
@@ -182,7 +230,7 @@ namespace Google.Protobuf
private static void AssertRoundtrip<T>(T message) where T : IMessage<T>, new()
{
var clone = message.Clone();
- var json = message.ToString();
+ var json = JsonFormatter.Default.Format(message);
var parsed = JsonParser.Default.Parse<T>(json);
Assert.AreEqual(clone, parsed);
}
@@ -429,7 +477,7 @@ namespace Google.Protobuf
[TestCase("-1", -1L)]
// long.MaxValue isn't actually representable as a double. This string value is the highest
// representable value which isn't greater than long.MaxValue.
- [TestCase("9223372036854769664", 9223372036854769664)]
+ [TestCase("9223372036854774784", 9223372036854774784)]
[TestCase("-9223372036854775808", -9223372036854775808)]
public void NumberToInt64_Valid(string jsonValue, long expectedParsedValue)
{
@@ -456,7 +504,7 @@ namespace Google.Protobuf
[TestCase("1", 1UL)]
// ulong.MaxValue isn't representable as a double. This value is the largest double within
// the range of ulong.
- [TestCase("18446744073709500416", 18446744073709500416UL)]
+ [TestCase("18446744073709549568", 18446744073709549568UL)]
public void NumberToUInt64_Valid(string jsonValue, ulong expectedParsedValue)
{
string json = "{ \"singleUint64\": " + jsonValue + "}";
@@ -715,7 +763,6 @@ namespace Google.Protobuf
[TestCase("--0.123456789s", Description = "Double minus sign")]
// Violate upper/lower bounds in various ways
[TestCase("315576000001s", Description = "Integer part too large")]
- [TestCase("315576000000.000000001s", Description = "Integer part is upper bound; non-zero fraction")]
[TestCase("3155760000000s", Description = "Integer part too long (positive)")]
[TestCase("-3155760000000s", Description = "Integer part too long (negative)")]
public void Duration_Invalid(string jsonValue)
@@ -742,6 +789,14 @@ namespace Google.Protobuf
}
[Test]
+ [TestCase("foo_bar")]
+ public void FieldMask_Invalid(string jsonValue)
+ {
+ string json = WrapInQuotes(jsonValue);
+ Assert.Throws<InvalidProtocolBufferException>(() => FieldMask.Parser.ParseJson(json));
+ }
+
+ [Test]
public void Any_RegularMessage()
{
var registry = TypeRegistry.FromMessages(TestAllTypes.Descriptor);
@@ -763,6 +818,13 @@ namespace Google.Protobuf
}
[Test]
+ public void Any_NoTypeUrl()
+ {
+ string json = "{ \"foo\": \"bar\" }";
+ Assert.Throws<InvalidProtocolBufferException>(() => Any.Parser.ParseJson(json));
+ }
+
+ [Test]
public void Any_WellKnownType()
{
var registry = TypeRegistry.FromMessages(Timestamp.Descriptor);
@@ -814,6 +876,42 @@ namespace Google.Protobuf
Assert.Throws<InvalidProtocolBufferException>(() => parser63.Parse<TestRecursiveMessage>(data64));
}
+ [Test]
+ [TestCase("AQI")]
+ [TestCase("_-==")]
+ public void Bytes_InvalidBase64(string badBase64)
+ {
+ string json = "{ \"singleBytes\": \"" + badBase64 + "\" }";
+ Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+ }
+
+ [Test]
+ [TestCase("\"FOREIGN_BAR\"", ForeignEnum.FOREIGN_BAR)]
+ [TestCase("5", ForeignEnum.FOREIGN_BAR)]
+ [TestCase("100", (ForeignEnum) 100)]
+ public void EnumValid(string value, ForeignEnum expectedValue)
+ {
+ string json = "{ \"singleForeignEnum\": " + value + " }";
+ var parsed = TestAllTypes.Parser.ParseJson(json);
+ Assert.AreEqual(new TestAllTypes { SingleForeignEnum = expectedValue }, parsed);
+ }
+
+ [Test]
+ [TestCase("\"NOT_A_VALID_VALUE\"")]
+ [TestCase("5.5")]
+ public void Enum_Invalid(string value)
+ {
+ string json = "{ \"singleForeignEnum\": " + value + " }";
+ Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+ }
+
+ [Test]
+ public void OneofDuplicate_Invalid()
+ {
+ string json = "{ \"oneofString\": \"x\", \"oneofUint32\": 10 }";
+ Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
+ }
+
/// <summary>
/// Various tests use strings which have quotes round them for parsing or as the result
/// of formatting, but without those quotes being specified in the tests (for the sake of readability).
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs b/csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs
new file mode 100644
index 00000000..5663a699
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs
@@ -0,0 +1,45 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+namespace Google.Protobuf.TestProtos
+{
+ /// <summary>
+ /// A message with custom diagnostics (to test that they work).
+ /// </summary>
+ public partial class ForeignMessage : ICustomDiagnosticMessage
+ {
+ public string ToDiagnosticString()
+ {
+ return $"{{ \"c\": {C}, \"@cInHex\": \"{C:x}\" }}";
+ }
+ }
+}
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
index dfada6bd..2079a960 100644
--- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
+++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
@@ -31,7 +31,7 @@ namespace Google.Protobuf.TestProtos {
"L3Byb3RvYnVmL3NvdXJjZV9jb250ZXh0LnByb3RvGhxnb29nbGUvcHJvdG9i",
"dWYvc3RydWN0LnByb3RvGh9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1wLnBy",
"b3RvGhpnb29nbGUvcHJvdG9idWYvdHlwZS5wcm90bxoeZ29vZ2xlL3Byb3Rv",
- "YnVmL3dyYXBwZXJzLnByb3RvIpEHChJUZXN0V2VsbEtub3duVHlwZXMSJwoJ",
+ "YnVmL3dyYXBwZXJzLnByb3RvIr4HChJUZXN0V2VsbEtub3duVHlwZXMSJwoJ",
"YW55X2ZpZWxkGAEgASgLMhQuZ29vZ2xlLnByb3RvYnVmLkFueRInCglhcGlf",
"ZmllbGQYAiABKAsyFC5nb29nbGUucHJvdG9idWYuQXBpEjEKDmR1cmF0aW9u",
"X2ZpZWxkGAMgASgLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEisKC2Vt",
@@ -51,7 +51,8 @@ namespace Google.Protobuf.TestProtos {
"cm90b2J1Zi5VSW50MzJWYWx1ZRIuCgpib29sX2ZpZWxkGBAgASgLMhouZ29v",
"Z2xlLnByb3RvYnVmLkJvb2xWYWx1ZRIyCgxzdHJpbmdfZmllbGQYESABKAsy",
"HC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUSMAoLYnl0ZXNfZmllbGQY",
- "EiABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZSKVBwoWUmVwZWF0",
+ "EiABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZRIrCgt2YWx1ZV9m",
+ "aWVsZBgTIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5WYWx1ZSKVBwoWUmVwZWF0",
"ZWRXZWxsS25vd25UeXBlcxInCglhbnlfZmllbGQYASADKAsyFC5nb29nbGUu",
"cHJvdG9idWYuQW55EicKCWFwaV9maWVsZBgCIAMoCzIULmdvb2dsZS5wcm90",
"b2J1Zi5BcGkSMQoOZHVyYXRpb25fZmllbGQYAyADKAsyGS5nb29nbGUucHJv",
@@ -162,7 +163,7 @@ namespace Google.Protobuf.TestProtos {
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.ApiReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.EmptyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.FieldMaskReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, },
new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
- new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestWellKnownTypes), global::Google.Protobuf.TestProtos.TestWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, null),
+ new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestWellKnownTypes), global::Google.Protobuf.TestProtos.TestWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField", "ValueField" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.RepeatedWellKnownTypes), global::Google.Protobuf.TestProtos.RepeatedWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.OneofWellKnownTypes), global::Google.Protobuf.TestProtos.OneofWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, new[]{ "OneofField" }, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.MapWellKnownTypes), global::Google.Protobuf.TestProtos.MapWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, new pbr::GeneratedCodeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, })
@@ -215,6 +216,7 @@ namespace Google.Protobuf.TestProtos {
BoolField = other.BoolField;
StringField = other.StringField;
BytesField = other.BytesField;
+ ValueField = other.valueField_ != null ? other.ValueField.Clone() : null;
}
public TestWellKnownTypes Clone() {
@@ -410,6 +412,19 @@ namespace Google.Protobuf.TestProtos {
}
}
+ /// <summary>Field number for the "value_field" field.</summary>
+ public const int ValueFieldFieldNumber = 19;
+ private global::Google.Protobuf.WellKnownTypes.Value valueField_;
+ /// <summary>
+ /// Part of struct, but useful to be able to test separately
+ /// </summary>
+ public global::Google.Protobuf.WellKnownTypes.Value ValueField {
+ get { return valueField_; }
+ set {
+ valueField_ = value;
+ }
+ }
+
public override bool Equals(object other) {
return Equals(other as TestWellKnownTypes);
}
@@ -439,6 +454,7 @@ namespace Google.Protobuf.TestProtos {
if (BoolField != other.BoolField) return false;
if (StringField != other.StringField) return false;
if (BytesField != other.BytesField) return false;
+ if (!object.Equals(ValueField, other.ValueField)) return false;
return true;
}
@@ -462,6 +478,7 @@ namespace Google.Protobuf.TestProtos {
if (boolField_ != null) hash ^= BoolField.GetHashCode();
if (stringField_ != null) hash ^= StringField.GetHashCode();
if (bytesField_ != null) hash ^= BytesField.GetHashCode();
+ if (valueField_ != null) hash ^= ValueField.GetHashCode();
return hash;
}
@@ -533,6 +550,10 @@ namespace Google.Protobuf.TestProtos {
if (bytesField_ != null) {
_single_bytesField_codec.WriteTagAndValue(output, BytesField);
}
+ if (valueField_ != null) {
+ output.WriteRawTag(154, 1);
+ output.WriteMessage(ValueField);
+ }
}
public int CalculateSize() {
@@ -591,6 +612,9 @@ namespace Google.Protobuf.TestProtos {
if (bytesField_ != null) {
size += _single_bytesField_codec.CalculateSizeWithTag(BytesField);
}
+ if (valueField_ != null) {
+ size += 2 + pb::CodedOutputStream.ComputeMessageSize(ValueField);
+ }
return size;
}
@@ -697,6 +721,12 @@ namespace Google.Protobuf.TestProtos {
BytesField = other.BytesField;
}
}
+ if (other.valueField_ != null) {
+ if (valueField_ == null) {
+ valueField_ = new global::Google.Protobuf.WellKnownTypes.Value();
+ }
+ ValueField.MergeFrom(other.ValueField);
+ }
}
public void MergeFrom(pb::CodedInputStream input) {
@@ -832,6 +862,13 @@ namespace Google.Protobuf.TestProtos {
}
break;
}
+ case 154: {
+ if (valueField_ == null) {
+ valueField_ = new global::Google.Protobuf.WellKnownTypes.Value();
+ }
+ input.ReadMessage(valueField_);
+ break;
+ }
}
}
}
diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs
index 36012e63..141faf80 100644
--- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs
+++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs
@@ -50,11 +50,6 @@ namespace Google.Protobuf.WellKnownTypes
// Rounding is towards 0
Assert.AreEqual(TimeSpan.FromTicks(2), new Duration { Nanos = 250 }.ToTimeSpan());
Assert.AreEqual(TimeSpan.FromTicks(-2), new Duration { Nanos = -250 }.ToTimeSpan());
-
- // Non-normalized durations
- Assert.AreEqual(TimeSpan.FromSeconds(3), new Duration { Seconds = 1, Nanos = 2 * Duration.NanosecondsPerSecond }.ToTimeSpan());
- Assert.AreEqual(TimeSpan.FromSeconds(1), new Duration { Seconds = 3, Nanos = -2 * Duration.NanosecondsPerSecond }.ToTimeSpan());
- Assert.AreEqual(TimeSpan.FromSeconds(-1), new Duration { Seconds = 1, Nanos = -2 * Duration.NanosecondsPerSecond }.ToTimeSpan());
}
[Test]
@@ -100,5 +95,38 @@ namespace Google.Protobuf.WellKnownTypes
Assert.AreEqual(new Duration { Seconds = 1 }, Duration.FromTimeSpan(TimeSpan.FromSeconds(1)));
Assert.AreEqual(new Duration { Nanos = Duration.NanosecondsPerTick }, Duration.FromTimeSpan(TimeSpan.FromTicks(1)));
}
+
+ [Test]
+ [TestCase(0, Duration.MaxNanoseconds + 1)]
+ [TestCase(0, Duration.MinNanoseconds - 1)]
+ [TestCase(Duration.MinSeconds - 1, 0)]
+ [TestCase(Duration.MaxSeconds + 1, 0)]
+ [TestCase(1, -1)]
+ [TestCase(-1, 1)]
+ public void ToTimeSpan_Invalid(long seconds, int nanoseconds)
+ {
+ var duration = new Duration { Seconds = seconds, Nanos = nanoseconds };
+ Assert.Throws<InvalidOperationException>(() => duration.ToTimeSpan());
+ }
+
+ [Test]
+ [TestCase(0, Duration.MaxNanoseconds)]
+ [TestCase(0, Duration.MinNanoseconds)]
+ [TestCase(Duration.MinSeconds, Duration.MinNanoseconds)]
+ [TestCase(Duration.MaxSeconds, Duration.MaxNanoseconds)]
+ public void ToTimeSpan_Valid(long seconds, int nanoseconds)
+ {
+ // Only testing that these values don't throw, unlike their similar tests in ToTimeSpan_Invalid
+ var duration = new Duration { Seconds = seconds, Nanos = nanoseconds };
+ duration.ToTimeSpan();
+ }
+
+ [Test]
+ public void ToString_NonNormalized()
+ {
+ // Just a single example should be sufficient...
+ var duration = new Duration { Seconds = 1, Nanos = -1 };
+ Assert.AreEqual("{ \"@warning\": \"Invalid Duration\", \"seconds\": \"1\", \"nanos\": -1 }", duration.ToString());
+ }
}
}
diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs
new file mode 100644
index 00000000..89bc8275
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs
@@ -0,0 +1,62 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+
+using NUnit.Framework;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+ public class FieldMaskTest
+ {
+ [Test]
+ [TestCase("foo__bar")]
+ [TestCase("foo_3_ar")]
+ [TestCase("fooBar")]
+ public void ToString_Invalid(string input)
+ {
+ var mask = new FieldMask { Paths = { input } };
+ var text = mask.ToString();
+ // More specific test below
+ Assert.That(text, Is.StringContaining("@warning"));
+ Assert.That(text, Is.StringContaining(input));
+ }
+
+ [Test]
+ public void ToString_Invalid_Precise()
+ {
+ var mask = new FieldMask { Paths = { "x", "foo__bar", @"x\y" } };
+ Assert.AreEqual(
+ "{ \"@warning\": \"Invalid FieldMask\", \"paths\": [ \"x\", \"foo__bar\", \"x\\\\y\" ] }",
+ mask.ToString());
+ }
+ }
+}
diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs
index 597539eb..9ecd24c6 100644
--- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs
+++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs
@@ -61,6 +61,29 @@ namespace Google.Protobuf.WellKnownTypes
Assert.AreEqual(new DateTime(1969, 12, 31, 23, 59, 59).AddMilliseconds(1), t2.ToDateTime());
}
+ [Test]
+ [TestCase(Timestamp.UnixSecondsAtBclMinValue - 1, Timestamp.MaxNanos)]
+ [TestCase(Timestamp.UnixSecondsAtBclMaxValue + 1, 0)]
+ [TestCase(0, -1)]
+ [TestCase(0, Timestamp.MaxNanos + 1)]
+ public void ToDateTime_OutOfRange(long seconds, int nanoseconds)
+ {
+ var value = new Timestamp { Seconds = seconds, Nanos = nanoseconds };
+ Assert.Throws<InvalidOperationException>(() => value.ToDateTime());
+ }
+
+ // 1ns larger or smaller than the above values
+ [Test]
+ [TestCase(Timestamp.UnixSecondsAtBclMinValue, 0)]
+ [TestCase(Timestamp.UnixSecondsAtBclMaxValue, Timestamp.MaxNanos)]
+ [TestCase(0, 0)]
+ [TestCase(0, Timestamp.MaxNanos)]
+ public void ToDateTime_ValidBoundaries(long seconds, int nanoseconds)
+ {
+ var value = new Timestamp { Seconds = seconds, Nanos = nanoseconds };
+ value.ToDateTime();
+ }
+
private static void AssertRoundtrip(Timestamp timestamp, DateTime dateTime)
{
Assert.AreEqual(timestamp, Timestamp.FromDateTime(dateTime));
@@ -80,5 +103,13 @@ namespace Google.Protobuf.WellKnownTypes
Assert.AreEqual(t1, t2 + difference);
Assert.AreEqual(t2, t1 - difference);
}
+
+ [Test]
+ public void ToString_NonNormalized()
+ {
+ // Just a single example should be sufficient...
+ var duration = new Timestamp { Seconds = 1, Nanos = -1 };
+ Assert.AreEqual("{ \"@warning\": \"Invalid Timestamp\", \"seconds\": \"1\", \"nanos\": -1 }", duration.ToString());
+ }
}
}
diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs
index b72ef982..a2c833fe 100644
--- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs
+++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs
@@ -149,6 +149,30 @@ namespace Google.Protobuf.WellKnownTypes
}
[Test]
+ public void RepeatedWrappersBinaryFormat()
+ {
+ // At one point we accidentally used a packed format for repeated wrappers, which is wrong (and weird).
+ // This test is just to prove that we use the right format.
+
+ var rawOutput = new MemoryStream();
+ var output = new CodedOutputStream(rawOutput);
+ // Write a value of 5
+ output.WriteTag(RepeatedWellKnownTypes.Int32FieldFieldNumber, WireFormat.WireType.LengthDelimited);
+ output.WriteLength(2);
+ output.WriteTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Varint);
+ output.WriteInt32(5);
+ // Write a value of 0 (empty message)
+ output.WriteTag(RepeatedWellKnownTypes.Int32FieldFieldNumber, WireFormat.WireType.LengthDelimited);
+ output.WriteLength(0);
+ output.Flush();
+ var expectedBytes = rawOutput.ToArray();
+
+ var message = new RepeatedWellKnownTypes { Int32Field = { 5, 0 } };
+ var actualBytes = message.ToByteArray();
+ Assert.AreEqual(expectedBytes, actualBytes);
+ }
+
+ [Test]
public void MapWrappersSerializeDeserialize()
{
// Note: no null values here, as they are prohibited in map fields
diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
index e3f65afe..1cde03bc 100644
--- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
+++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
@@ -34,7 +34,6 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
-using Google.Protobuf.Compatibility;
namespace Google.Protobuf.Collections
{
@@ -96,8 +95,8 @@ namespace Google.Protobuf.Collections
// iteration.
uint tag = input.LastTag;
var reader = codec.ValueReader;
- // Value types can be packed or not.
- if (typeof(T).IsValueType() && WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited)
+ // Non-nullable value types can be packed or not.
+ if (FieldCodec<T>.IsPackedRepeatedField(tag))
{
int length = input.ReadLength();
if (length > 0)
@@ -134,7 +133,7 @@ namespace Google.Protobuf.Collections
return 0;
}
uint tag = codec.Tag;
- if (typeof(T).IsValueType() && WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited)
+ if (codec.PackedRepeatedField)
{
int dataSize = CalculatePackedDataSize(codec);
return CodedOutputStream.ComputeRawVarint32Size(tag) +
@@ -186,7 +185,7 @@ namespace Google.Protobuf.Collections
}
var writer = codec.ValueWriter;
var tag = codec.Tag;
- if (typeof(T).IsValueType() && WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited)
+ if (codec.PackedRepeatedField)
{
// Packed primitive type
uint size = (uint)CalculatePackedDataSize(codec);
diff --git a/csharp/src/Google.Protobuf/FieldCodec.cs b/csharp/src/Google.Protobuf/FieldCodec.cs
index c2b8d268..98313088 100644
--- a/csharp/src/Google.Protobuf/FieldCodec.cs
+++ b/csharp/src/Google.Protobuf/FieldCodec.cs
@@ -30,6 +30,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
+using Google.Protobuf.Compatibility;
using Google.Protobuf.WellKnownTypes;
using System;
using System.Collections.Generic;
@@ -329,17 +330,24 @@ namespace Google.Protobuf
}
/// <summary>
+ /// <para>
/// An encode/decode pair for a single field. This effectively encapsulates
/// all the information needed to read or write the field value from/to a coded
/// stream.
+ /// </para>
+ /// <para>
+ /// This class is public and has to be as it is used by generated code, but its public
+ /// API is very limited - just what the generated code needs to call directly.
+ /// </para>
/// </summary>
/// <remarks>
- /// This never writes default values to the stream, and is not currently designed
- /// to play well with packed arrays.
+ /// This never writes default values to the stream, and does not address "packedness"
+ /// in repeated fields itself, other than to know whether or not the field *should* be packed.
/// </remarks>
public sealed class FieldCodec<T>
{
private static readonly T DefaultDefault;
+ private static readonly bool TypeSupportsPacking = typeof(T).IsValueType() && Nullable.GetUnderlyingType(typeof(T)) == null;
static FieldCodec()
{
@@ -354,75 +362,31 @@ namespace Google.Protobuf
// Otherwise it's the default value of the CLR type
}
- private readonly Func<CodedInputStream, T> reader;
- private readonly Action<CodedOutputStream, T> writer;
- private readonly Func<T, int> sizeCalculator;
- private readonly uint tag;
- private readonly int tagSize;
- private readonly int fixedSize;
- // Default value for this codec. Usually the same for every instance of the same type, but
- // for string/ByteString wrapper fields the codec's default value is null, whereas for
- // other string/ByteString fields it's "" or ByteString.Empty.
- private readonly T defaultValue;
+ internal static bool IsPackedRepeatedField(uint tag) =>
+ TypeSupportsPacking && WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited;
- internal FieldCodec(
- Func<CodedInputStream, T> reader,
- Action<CodedOutputStream, T> writer,
- Func<T, int> sizeCalculator,
- uint tag) : this(reader, writer, sizeCalculator, tag, DefaultDefault)
- {
- }
-
- internal FieldCodec(
- Func<CodedInputStream, T> reader,
- Action<CodedOutputStream, T> writer,
- Func<T, int> sizeCalculator,
- uint tag,
- T defaultValue)
- {
- this.reader = reader;
- this.writer = writer;
- this.sizeCalculator = sizeCalculator;
- this.fixedSize = 0;
- this.tag = tag;
- this.defaultValue = defaultValue;
- tagSize = CodedOutputStream.ComputeRawVarint32Size(tag);
- }
-
- internal FieldCodec(
- Func<CodedInputStream, T> reader,
- Action<CodedOutputStream, T> writer,
- int fixedSize,
- uint tag)
- {
- this.reader = reader;
- this.writer = writer;
- this.sizeCalculator = _ => fixedSize;
- this.fixedSize = fixedSize;
- this.tag = tag;
- tagSize = CodedOutputStream.ComputeRawVarint32Size(tag);
- }
+ internal bool PackedRepeatedField { get; }
/// <summary>
- /// Returns the size calculator for just a value.
+ /// Returns a delegate to write a value (unconditionally) to a coded output stream.
/// </summary>
- internal Func<T, int> ValueSizeCalculator { get { return sizeCalculator; } }
+ internal Action<CodedOutputStream, T> ValueWriter { get; }
/// <summary>
- /// Returns a delegate to write a value (unconditionally) to a coded output stream.
+ /// Returns the size calculator for just a value.
/// </summary>
- internal Action<CodedOutputStream, T> ValueWriter { get { return writer; } }
+ internal Func<T, int> ValueSizeCalculator { get; }
/// <summary>
/// Returns a delegate to read a value from a coded input stream. It is assumed that
/// the stream is already positioned on the appropriate tag.
/// </summary>
- internal Func<CodedInputStream, T> ValueReader { get { return reader; } }
+ internal Func<CodedInputStream, T> ValueReader { get; }
/// <summary>
/// Returns the fixed size for an entry, or 0 if sizes vary.
/// </summary>
- internal int FixedSize { get { return fixedSize; } }
+ internal int FixedSize { get; }
/// <summary>
/// Gets the tag of the codec.
@@ -430,15 +394,54 @@ namespace Google.Protobuf
/// <value>
/// The tag of the codec.
/// </value>
- public uint Tag { get { return tag; } }
+ internal uint Tag { get; }
/// <summary>
- /// Gets the default value of the codec's type.
+ /// Default value for this codec. Usually the same for every instance of the same type, but
+ /// for string/ByteString wrapper fields the codec's default value is null, whereas for
+ /// other string/ByteString fields it's "" or ByteString.Empty.
/// </summary>
/// <value>
/// The default value of the codec's type.
/// </value>
- public T DefaultValue { get { return defaultValue; } }
+ internal T DefaultValue { get; }
+
+ private readonly int tagSize;
+
+ internal FieldCodec(
+ Func<CodedInputStream, T> reader,
+ Action<CodedOutputStream, T> writer,
+ int fixedSize,
+ uint tag) : this(reader, writer, _ => fixedSize, tag)
+ {
+ FixedSize = fixedSize;
+ }
+
+ internal FieldCodec(
+ Func<CodedInputStream, T> reader,
+ Action<CodedOutputStream, T> writer,
+ Func<T, int> sizeCalculator,
+ uint tag) : this(reader, writer, sizeCalculator, tag, DefaultDefault)
+ {
+ }
+
+ internal FieldCodec(
+ Func<CodedInputStream, T> reader,
+ Action<CodedOutputStream, T> writer,
+ Func<T, int> sizeCalculator,
+ uint tag,
+ T defaultValue)
+ {
+ ValueReader = reader;
+ ValueWriter = writer;
+ ValueSizeCalculator = sizeCalculator;
+ FixedSize = 0;
+ Tag = tag;
+ DefaultValue = defaultValue;
+ tagSize = CodedOutputStream.ComputeRawVarint32Size(tag);
+ // Detect packed-ness once, so we can check for it within RepeatedField<T>.
+ PackedRepeatedField = IsPackedRepeatedField(tag);
+ }
/// <summary>
/// Write a tag and the given value, *if* the value is not the default.
@@ -447,8 +450,8 @@ namespace Google.Protobuf
{
if (!IsDefault(value))
{
- output.WriteTag(tag);
- writer(output, value);
+ output.WriteTag(Tag);
+ ValueWriter(output, value);
}
}
@@ -457,23 +460,14 @@ namespace Google.Protobuf
/// </summary>
/// <param name="input">The input stream to read from.</param>
/// <returns>The value read from the stream.</returns>
- public T Read(CodedInputStream input)
- {
- return reader(input);
- }
+ public T Read(CodedInputStream input) => ValueReader(input);
/// <summary>
/// Calculates the size required to write the given value, with a tag,
/// if the value is not the default.
/// </summary>
- public int CalculateSizeWithTag(T value)
- {
- return IsDefault(value) ? 0 : sizeCalculator(value) + tagSize;
- }
+ public int CalculateSizeWithTag(T value) => IsDefault(value) ? 0 : ValueSizeCalculator(value) + tagSize;
- private bool IsDefault(T value)
- {
- return EqualityComparer<T>.Default.Equals(value, defaultValue);
- }
+ private bool IsDefault(T value) => EqualityComparer<T>.Default.Equals(value, DefaultValue);
}
}
diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
index e6af2483..f95bae07 100644
--- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj
+++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
@@ -85,6 +85,7 @@
<Compile Include="Compatibility\TypeExtensions.cs" />
<Compile Include="FieldCodec.cs" />
<Compile Include="FrameworkPortability.cs" />
+ <Compile Include="ICustomDiagnosticMessage.cs" />
<Compile Include="IDeepCloneable.cs" />
<Compile Include="InvalidJsonException.cs" />
<Compile Include="JsonFormatter.cs" />
@@ -131,6 +132,7 @@
<Compile Include="WellKnownTypes\DurationPartial.cs" />
<Compile Include="WellKnownTypes\Empty.cs" />
<Compile Include="WellKnownTypes\FieldMask.cs" />
+ <Compile Include="WellKnownTypes\FieldMaskPartial.cs" />
<Compile Include="WellKnownTypes\SourceContext.cs" />
<Compile Include="WellKnownTypes\Struct.cs" />
<Compile Include="WellKnownTypes\TimeExtensions.cs" />
diff --git a/csharp/src/Google.Protobuf/ICustomDiagnosticMessage.cs b/csharp/src/Google.Protobuf/ICustomDiagnosticMessage.cs
new file mode 100644
index 00000000..a0090569
--- /dev/null
+++ b/csharp/src/Google.Protobuf/ICustomDiagnosticMessage.cs
@@ -0,0 +1,69 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+namespace Google.Protobuf
+{
+ /// <summary>
+ /// A message type that has a custom string format for diagnostic purposes.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Calling <see cref="object.ToString"/> on a generated message type normally
+ /// returns the JSON representation. If a message type implements this interface,
+ /// then the <see cref="ToDiagnosticString"/> method will be called instead of the regular
+ /// JSON formatting code, but only when <c>ToString()</c> is called either on the message itself
+ /// or on another message which contains it. This does not affect the normal JSON formatting of
+ /// the message.
+ /// </para>
+ /// <para>
+ /// For example, if you create a proto message representing a GUID, the internal
+ /// representation may be a <c>bytes</c> field or four <c>fixed32</c> fields. However, when debugging
+ /// it may be more convenient to see a result in the same format as <see cref="System.Guid"/> provides.
+ /// </para>
+ /// <para>This interface extends <see cref="IMessage"/> to avoid it accidentally being implemented
+ /// on types other than messages, where it would not be used by anything in the framework.</para>
+ /// </remarks>
+ public interface ICustomDiagnosticMessage : IMessage
+ {
+ /// <summary>
+ /// Returns a string representation of this object, for diagnostic purposes.
+ /// </summary>
+ /// <remarks>
+ /// This method is called when a message is formatted as part of a <see cref="object.ToString"/>
+ /// call. It does not affect the JSON representation used by <see cref="JsonFormatter"/> other than
+ /// in calls to <see cref="JsonFormatter.ToDiagnosticString(IMessage)"/>. While it is recommended
+ /// that the result is valid JSON, this is never assumed by the Protobuf library.
+ /// </remarks>
+ /// <returns>A string representation of this object, for diagnostic purposes.</returns>
+ string ToDiagnosticString();
+ }
+}
diff --git a/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs b/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs
index cacda648..eeb0f13a 100644
--- a/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs
+++ b/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs
@@ -30,6 +30,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
+using System;
using System.IO;
namespace Google.Protobuf
@@ -45,6 +46,11 @@ namespace Google.Protobuf
{
}
+ internal InvalidProtocolBufferException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+
internal static InvalidProtocolBufferException MoreDataAvailable()
{
return new InvalidProtocolBufferException(
@@ -82,6 +88,11 @@ namespace Google.Protobuf
"Protocol message contained an invalid tag (zero).");
}
+ internal static InvalidProtocolBufferException InvalidBase64(Exception innerException)
+ {
+ return new InvalidProtocolBufferException("Invalid base64 data", innerException);
+ }
+
internal static InvalidProtocolBufferException InvalidEndTag()
{
return new InvalidProtocolBufferException(
diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs
index bde17903..17495747 100644
--- a/csharp/src/Google.Protobuf/JsonFormatter.cs
+++ b/csharp/src/Google.Protobuf/JsonFormatter.cs
@@ -37,6 +37,7 @@ using System.Text;
using Google.Protobuf.Reflection;
using Google.Protobuf.WellKnownTypes;
using System.Linq;
+using System.Collections.Generic;
namespace Google.Protobuf
{
@@ -122,6 +123,8 @@ namespace Google.Protobuf
private readonly Settings settings;
+ private bool DiagnosticOnly => ReferenceEquals(this, diagnosticFormatter);
+
/// <summary>
/// Creates a new formatted with the given settings.
/// </summary>
@@ -181,6 +184,15 @@ namespace Google.Protobuf
WriteNull(builder);
return;
}
+ if (DiagnosticOnly)
+ {
+ ICustomDiagnosticMessage customDiagnosticMessage = message as ICustomDiagnosticMessage;
+ if (customDiagnosticMessage != null)
+ {
+ builder.Append(customDiagnosticMessage.ToDiagnosticString());
+ return;
+ }
+ }
builder.Append("{ ");
bool writtenFields = WriteMessageFields(builder, message, false);
builder.Append(writtenFields ? " }" : "}");
@@ -205,11 +217,6 @@ namespace Google.Protobuf
{
continue;
}
- // Omit awkward (single) values such as unknown enum values
- if (!field.IsRepeated && !field.IsMap && !CanWriteSingleValue(value))
- {
- continue;
- }
// Okay, all tests complete: let's write the field value...
if (!first)
@@ -224,6 +231,31 @@ namespace Google.Protobuf
return !first;
}
+ /// <summary>
+ /// Camel-case converter with added strictness for field mask formatting.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">The field mask is invalid for JSON representation</exception>
+ private static string ToCamelCaseForFieldMask(string input)
+ {
+ for (int i = 0; i < input.Length; i++)
+ {
+ char c = input[i];
+ if (c >= 'A' && c <= 'Z')
+ {
+ throw new InvalidOperationException($"Invalid field mask to be converted to JSON: {input}");
+ }
+ if (c == '_' && i < input.Length - 1)
+ {
+ char next = input[i + 1];
+ if (next < 'a' || next > 'z')
+ {
+ throw new InvalidOperationException($"Invalid field mask to be converted to JSON: {input}");
+ }
+ }
+ }
+ return ToCamelCase(input);
+ }
+
// Converted from src/google/protobuf/util/internal/utility.cc ToCamelCase
// TODO: Use the new field in FieldDescriptor.
internal static string ToCamelCase(string input)
@@ -372,7 +404,14 @@ namespace Google.Protobuf
}
else if (value is System.Enum)
{
- WriteString(builder, value.ToString());
+ if (System.Enum.IsDefined(value.GetType(), value))
+ {
+ WriteString(builder, value.ToString());
+ }
+ else
+ {
+ WriteValue(builder, (int) value);
+ }
}
else if (value is float || value is double)
{
@@ -477,55 +516,32 @@ namespace Google.Protobuf
private void WriteTimestamp(StringBuilder builder, IMessage value)
{
- builder.Append('"');
// TODO: In the common case where this *is* using the built-in Timestamp type, we could
// avoid all the reflection at this point, by casting to Timestamp. In the interests of
// avoiding subtle bugs, don't do that until we've implemented DynamicMessage so that we can prove
// it still works in that case.
int nanos = (int) value.Descriptor.Fields[Timestamp.NanosFieldNumber].Accessor.GetValue(value);
long seconds = (long) value.Descriptor.Fields[Timestamp.SecondsFieldNumber].Accessor.GetValue(value);
-
- // Even if the original message isn't using the built-in classes, we can still build one... and then
- // rely on it being normalized.
- Timestamp normalized = Timestamp.Normalize(seconds, nanos);
- // Use .NET's formatting for the value down to the second, including an opening double quote (as it's a string value)
- DateTime dateTime = normalized.ToDateTime();
- builder.Append(dateTime.ToString("yyyy'-'MM'-'dd'T'HH:mm:ss", CultureInfo.InvariantCulture));
- AppendNanoseconds(builder, Math.Abs(normalized.Nanos));
- builder.Append("Z\"");
+ builder.Append(Timestamp.ToJson(seconds, nanos, DiagnosticOnly));
}
private void WriteDuration(StringBuilder builder, IMessage value)
{
- builder.Append('"');
// TODO: Same as for WriteTimestamp
int nanos = (int) value.Descriptor.Fields[Duration.NanosFieldNumber].Accessor.GetValue(value);
long seconds = (long) value.Descriptor.Fields[Duration.SecondsFieldNumber].Accessor.GetValue(value);
-
- // Even if the original message isn't using the built-in classes, we can still build one... and then
- // rely on it being normalized.
- Duration normalized = Duration.Normalize(seconds, nanos);
-
- // The seconds part will normally provide the minus sign if we need it, but not if it's 0...
- if (normalized.Seconds == 0 && normalized.Nanos < 0)
- {
- builder.Append('-');
- }
-
- builder.Append(normalized.Seconds.ToString("d", CultureInfo.InvariantCulture));
- AppendNanoseconds(builder, Math.Abs(normalized.Nanos));
- builder.Append("s\"");
+ builder.Append(Duration.ToJson(seconds, nanos, DiagnosticOnly));
}
private void WriteFieldMask(StringBuilder builder, IMessage value)
{
- IList paths = (IList) value.Descriptor.Fields[FieldMask.PathsFieldNumber].Accessor.GetValue(value);
- WriteString(builder, string.Join(",", paths.Cast<string>().Select(ToCamelCase)));
+ var paths = (IList<string>) value.Descriptor.Fields[FieldMask.PathsFieldNumber].Accessor.GetValue(value);
+ builder.Append(FieldMask.ToJson(paths, DiagnosticOnly));
}
private void WriteAny(StringBuilder builder, IMessage value)
{
- if (ReferenceEquals(this, diagnosticFormatter))
+ if (DiagnosticOnly)
{
WriteDiagnosticOnlyAny(builder, value);
return;
@@ -586,31 +602,6 @@ namespace Google.Protobuf
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.
- /// </summary>
- private static void AppendNanoseconds(StringBuilder builder, int nanos)
- {
- if (nanos != 0)
- {
- builder.Append('.');
- // Output to 3, 6 or 9 digits.
- if (nanos % 1000000 == 0)
- {
- builder.Append((nanos / 1000000).ToString("d", CultureInfo.InvariantCulture));
- }
- else if (nanos % 1000 == 0)
- {
- builder.Append((nanos / 1000).ToString("d", CultureInfo.InvariantCulture));
- }
- else
- {
- builder.Append(nanos.ToString("d", CultureInfo.InvariantCulture));
- }
- }
- }
-
private void WriteStruct(StringBuilder builder, IMessage message)
{
builder.Append("{ ");
@@ -674,10 +665,6 @@ namespace Google.Protobuf
bool first = true;
foreach (var value in list)
{
- if (!CanWriteSingleValue(value))
- {
- continue;
- }
if (!first)
{
builder.Append(PropertySeparator);
@@ -695,10 +682,6 @@ namespace Google.Protobuf
// This will box each pair. Could use IDictionaryEnumerator, but that's ugly in terms of disposal.
foreach (DictionaryEntry pair in dictionary)
{
- if (!CanWriteSingleValue(pair.Value))
- {
- continue;
- }
if (!first)
{
builder.Append(PropertySeparator);
@@ -752,7 +735,7 @@ namespace Google.Protobuf
/// <remarks>
/// Other than surrogate pair handling, this code is mostly taken from src/google/protobuf/util/internal/json_escaping.cc.
/// </remarks>
- private void WriteString(StringBuilder builder, string text)
+ internal static void WriteString(StringBuilder builder, string text)
{
builder.Append('"');
for (int i = 0; i < text.Length; i++)
diff --git a/csharp/src/Google.Protobuf/JsonParser.cs b/csharp/src/Google.Protobuf/JsonParser.cs
index 300a66b4..c07b16ea 100644
--- a/csharp/src/Google.Protobuf/JsonParser.cs
+++ b/csharp/src/Google.Protobuf/JsonParser.cs
@@ -168,6 +168,10 @@ namespace Google.Protobuf
}
var descriptor = message.Descriptor;
var jsonFieldMap = descriptor.Fields.ByJsonName();
+ // All the oneof fields we've already accounted for - we can only see each of them once.
+ // The set is created lazily to avoid the overhead of creating a set for every message
+ // we parsed, when oneofs are relatively rare.
+ HashSet<OneofDescriptor> seenOneofs = null;
while (true)
{
token = tokenizer.Next();
@@ -183,6 +187,17 @@ namespace Google.Protobuf
FieldDescriptor field;
if (jsonFieldMap.TryGetValue(name, out field))
{
+ if (field.ContainingOneof != null)
+ {
+ if (seenOneofs == null)
+ {
+ seenOneofs = new HashSet<OneofDescriptor>();
+ }
+ if (!seenOneofs.Add(field.ContainingOneof))
+ {
+ throw new InvalidProtocolBufferException($"Multiple values specified for oneof {field.ContainingOneof.Name}");
+ }
+ }
MergeField(message, field, tokenizer);
}
else
@@ -200,10 +215,15 @@ namespace Google.Protobuf
var token = tokenizer.Next();
if (token.Type == JsonToken.TokenType.Null)
{
+ // Clear the field if we see a null token, unless it's for a singular field of type
+ // google.protobuf.Value.
// Note: different from Java API, which just ignores it.
// TODO: Bring it more in line? Discuss...
- field.Accessor.Clear(message);
- return;
+ if (field.IsMap || field.IsRepeated || !IsGoogleProtobufValueField(field))
+ {
+ field.Accessor.Clear(message);
+ return;
+ }
}
tokenizer.PushBack(token);
@@ -239,6 +259,10 @@ namespace Google.Protobuf
return;
}
tokenizer.PushBack(token);
+ if (token.Type == JsonToken.TokenType.Null)
+ {
+ throw new InvalidProtocolBufferException("Repeated field elements cannot be null");
+ }
list.Add(ParseSingleValue(field, tokenizer));
}
}
@@ -270,19 +294,30 @@ namespace Google.Protobuf
}
object key = ParseMapKey(keyField, token.StringValue);
object value = ParseSingleValue(valueField, tokenizer);
- // TODO: Null handling
+ if (value == null)
+ {
+ throw new InvalidProtocolBufferException("Map values must not be null");
+ }
dictionary[key] = value;
}
}
+ private static bool IsGoogleProtobufValueField(FieldDescriptor field)
+ {
+ return field.FieldType == FieldType.Message &&
+ field.MessageType.FullName == Value.Descriptor.FullName;
+ }
+
private object ParseSingleValue(FieldDescriptor field, JsonTokenizer tokenizer)
{
var token = tokenizer.Next();
if (token.Type == JsonToken.TokenType.Null)
{
- if (field.FieldType == FieldType.Message && field.MessageType.FullName == Value.Descriptor.FullName)
+ // TODO: In order to support dynamic messages, we should really build this up
+ // dynamically.
+ if (IsGoogleProtobufValueField(field))
{
- return new Value { NullValue = NullValue.NULL_VALUE };
+ return Value.ForNull();
}
return null;
}
@@ -464,6 +499,11 @@ namespace Google.Protobuf
{
tokens.Add(token);
token = tokenizer.Next();
+
+ if (tokenizer.ObjectDepth < typeUrlObjectDepth)
+ {
+ throw new InvalidProtocolBufferException("Any message with no @type");
+ }
}
// Don't add the @type property or its value to the recorded token list
@@ -603,6 +643,11 @@ namespace Google.Protobuf
throw new InvalidProtocolBufferException($"Value out of range: {value}");
}
return (float) value;
+ case FieldType.Enum:
+ CheckInteger(value);
+ // Just return it as an int, and let the CLR convert it.
+ // Note that we deliberately don't check that it's a known value.
+ return (int) value;
default:
throw new InvalidProtocolBufferException($"Unsupported conversion from JSON number for field type {field.FieldType}");
}
@@ -633,7 +678,14 @@ namespace Google.Protobuf
case FieldType.String:
return text;
case FieldType.Bytes:
- return ByteString.FromBase64(text);
+ try
+ {
+ return ByteString.FromBase64(text);
+ }
+ catch (FormatException e)
+ {
+ throw InvalidProtocolBufferException.InvalidBase64(e);
+ }
case FieldType.Int32:
case FieldType.SInt32:
case FieldType.SFixed32:
@@ -826,28 +878,24 @@ namespace Google.Protobuf
try
{
- long seconds = long.Parse(secondsText, CultureInfo.InvariantCulture);
+ long seconds = long.Parse(secondsText, CultureInfo.InvariantCulture) * multiplier;
int nanos = 0;
if (subseconds != "")
{
// This should always work, as we've got 1-9 digits.
int parsedFraction = int.Parse(subseconds.Substring(1));
- nanos = parsedFraction * SubsecondScalingFactors[subseconds.Length];
+ nanos = parsedFraction * SubsecondScalingFactors[subseconds.Length] * multiplier;
}
- if (seconds >= Duration.MaxSeconds)
+ if (!Duration.IsNormalized(seconds, nanos))
{
- // Allow precisely 315576000000 seconds, but prohibit even 1ns more.
- if (seconds > Duration.MaxSeconds || nanos > 0)
- {
- throw new InvalidProtocolBufferException("Invalid Duration value: " + token.StringValue);
- }
+ throw new InvalidProtocolBufferException($"Invalid Duration value: {token.StringValue}");
}
- message.Descriptor.Fields[Duration.SecondsFieldNumber].Accessor.SetValue(message, seconds * multiplier);
- message.Descriptor.Fields[Duration.NanosFieldNumber].Accessor.SetValue(message, nanos * multiplier);
+ message.Descriptor.Fields[Duration.SecondsFieldNumber].Accessor.SetValue(message, seconds);
+ message.Descriptor.Fields[Duration.NanosFieldNumber].Accessor.SetValue(message, nanos);
}
catch (FormatException)
{
- throw new InvalidProtocolBufferException("Invalid Duration value: " + token.StringValue);
+ throw new InvalidProtocolBufferException($"Invalid Duration value: {token.StringValue}");
}
}
@@ -870,6 +918,8 @@ namespace Google.Protobuf
private static string ToSnakeCase(string text)
{
var builder = new StringBuilder(text.Length * 2);
+ // Note: this is probably unnecessary now, but currently retained to be as close as possible to the
+ // C++, whilst still throwing an exception on underscores.
bool wasNotUnderscore = false; // Initialize to false for case 1 (below)
bool wasNotCap = false;
@@ -903,7 +953,11 @@ namespace Google.Protobuf
else
{
builder.Append(c);
- wasNotUnderscore = c != '_';
+ if (c == '_')
+ {
+ throw new InvalidProtocolBufferException($"Invalid field mask: {text}");
+ }
+ wasNotUnderscore = true;
wasNotCap = true;
}
}
diff --git a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
index d1732b2e..f43803a6 100644
--- a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
@@ -92,11 +92,22 @@ namespace Google.Protobuf.Reflection
new FieldDescriptor(field, file, this, index, generatedCodeInfo?.PropertyNames[index]));
fieldsInNumberOrder = new ReadOnlyCollection<FieldDescriptor>(fieldsInDeclarationOrder.OrderBy(field => field.FieldNumber).ToArray());
// TODO: Use field => field.Proto.JsonName when we're confident it's appropriate. (And then use it in the formatter, too.)
- jsonFieldMap = new ReadOnlyDictionary<string, FieldDescriptor>(fieldsInNumberOrder.ToDictionary(field => JsonFormatter.ToCamelCase(field.Name)));
+ jsonFieldMap = CreateJsonFieldMap(fieldsInNumberOrder);
file.DescriptorPool.AddSymbol(this);
Fields = new FieldCollection(this);
}
+ private static ReadOnlyDictionary<string, FieldDescriptor> CreateJsonFieldMap(IList<FieldDescriptor> fields)
+ {
+ var map = new Dictionary<string, FieldDescriptor>();
+ foreach (var field in fields)
+ {
+ map[JsonFormatter.ToCamelCase(field.Name)] = field;
+ map[field.Name] = field;
+ }
+ return new ReadOnlyDictionary<string, FieldDescriptor>(map);
+ }
+
/// <summary>
/// The brief name of the descriptor's target.
/// </summary>
@@ -255,9 +266,10 @@ namespace Google.Protobuf.Reflection
// TODO: consider making this public in the future. (Being conservative for now...)
/// <value>
- /// Returns a read-only dictionary mapping the field names in this message as they're used
+ /// Returns a read-only dictionary mapping the field names in this message as they're available
/// in the JSON representation to the field descriptors. For example, a field <c>foo_bar</c>
- /// in the message would result in an entry with a key <c>fooBar</c>.
+ /// in the message would result two entries, one with a key <c>fooBar</c> and one with a key
+ /// <c>foo_bar</c>, both referring to the same field.
/// </value>
internal IDictionary<string, FieldDescriptor> ByJsonName() => messageDescriptor.jsonFieldMap;
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs
index 324f48fc..e5247e90 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs
@@ -31,12 +31,14 @@
#endregion
using System;
+using System.Globalization;
+using System.Text;
namespace Google.Protobuf.WellKnownTypes
{
// Manually-written partial class for the Duration well-known type,
// providing a conversion to TimeSpan and convenience operators.
- public partial class Duration
+ public partial class Duration : ICustomDiagnosticMessage
{
/// <summary>
/// The number of nanoseconds in a second.
@@ -57,15 +59,37 @@ namespace Google.Protobuf.WellKnownTypes
/// </summary>
public const long MinSeconds = -315576000000L;
+ internal const int MaxNanoseconds = NanosecondsPerSecond - 1;
+ internal const int MinNanoseconds = -NanosecondsPerSecond + 1;
+
+ internal static bool IsNormalized(long seconds, int nanoseconds)
+ {
+ // Simple boundaries
+ if (seconds < MinSeconds || seconds > MaxSeconds ||
+ nanoseconds < MinNanoseconds || nanoseconds > MaxNanoseconds)
+ {
+ return false;
+ }
+ // We only have a problem is one is strictly negative and the other is
+ // strictly positive.
+ return Math.Sign(seconds) * Math.Sign(nanoseconds) != -1;
+ }
+
/// <summary>
/// Converts this <see cref="Duration"/> to a <see cref="TimeSpan"/>.
/// </summary>
/// <remarks>If the duration is not a precise number of ticks, it is truncated towards 0.</remarks>
/// <returns>The value of this duration, as a <c>TimeSpan</c>.</returns>
+ /// <exception cref="InvalidOperationException">This value isn't a valid normalized duration, as
+ /// described in the documentation.</exception>
public TimeSpan ToTimeSpan()
{
checked
{
+ if (!IsNormalized(Seconds, Nanos))
+ {
+ throw new InvalidOperationException("Duration was not a valid normalized duration");
+ }
long ticks = Seconds * TimeSpan.TicksPerSecond + Nanos / NanosecondsPerTick;
return TimeSpan.FromTicks(ticks);
}
@@ -157,5 +181,90 @@ namespace Google.Protobuf.WellKnownTypes
}
return new Duration { Seconds = seconds, Nanos = nanoseconds };
}
+
+ /// <summary>
+ /// Converts a duration specified in seconds/nanoseconds to a string.
+ /// </summary>
+ /// <remarks>
+ /// If the value is a normalized duration in the range described in <c>duration.proto</c>,
+ /// <paramref name="diagnosticOnly"/> is ignored. Otherwise, if the parameter is <c>true</c>,
+ /// a JSON object with a warning is returned; if it is <c>false</c>, an <see cref="InvalidOperationException"/> is thrown.
+ /// </remarks>
+ /// <param name="seconds">Seconds portion of the duration.</param>
+ /// <param name="nanoseconds">Nanoseconds portion of the duration.</param>
+ /// <param name="diagnosticOnly">Determines the handling of non-normalized values</param>
+ /// <exception cref="InvalidOperationException">The represented duration is invalid, and <paramref name="diagnosticOnly"/> is <c>false</c>.</exception>
+ internal static string ToJson(long seconds, int nanoseconds, bool diagnosticOnly)
+ {
+ if (IsNormalized(seconds, nanoseconds))
+ {
+ var builder = new StringBuilder();
+ builder.Append('"');
+ // The seconds part will normally provide the minus sign if we need it, but not if it's 0...
+ if (seconds == 0 && nanoseconds < 0)
+ {
+ builder.Append('-');
+ }
+
+ builder.Append(seconds.ToString("d", CultureInfo.InvariantCulture));
+ AppendNanoseconds(builder, Math.Abs(nanoseconds));
+ builder.Append("s\"");
+ return builder.ToString();
+ }
+ if (diagnosticOnly)
+ {
+ // Note: the double braces here are escaping for braces in format strings.
+ return string.Format(CultureInfo.InvariantCulture,
+ "{{ \"@warning\": \"Invalid Duration\", \"seconds\": \"{0}\", \"nanos\": {1} }}",
+ seconds,
+ nanoseconds);
+ }
+ else
+ {
+ throw new InvalidOperationException("Non-normalized duration value");
+ }
+ }
+
+ /// <summary>
+ /// Returns a string representation of this <see cref="Duration"/> for diagnostic purposes.
+ /// </summary>
+ /// <remarks>
+ /// Normally the returned value will be a JSON string value (including leading and trailing quotes) but
+ /// when the value is non-normalized or out of range, a JSON object representation will be returned
+ /// instead, including a warning. This is to avoid exceptions being thrown when trying to
+ /// diagnose problems - the regular JSON formatter will still throw an exception for non-normalized
+ /// values.
+ /// </remarks>
+ /// <returns>A string representation of this value.</returns>
+ public string ToDiagnosticString()
+ {
+ return ToJson(Seconds, Nanos, true);
+ }
+
+ /// <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. This is internal for use in Timestamp as well
+ /// as Duration.
+ /// </summary>
+ internal static void AppendNanoseconds(StringBuilder builder, int nanos)
+ {
+ if (nanos != 0)
+ {
+ builder.Append('.');
+ // Output to 3, 6 or 9 digits.
+ if (nanos % 1000000 == 0)
+ {
+ builder.Append((nanos / 1000000).ToString("d3", CultureInfo.InvariantCulture));
+ }
+ else if (nanos % 1000 == 0)
+ {
+ builder.Append((nanos / 1000).ToString("d6", CultureInfo.InvariantCulture));
+ }
+ else
+ {
+ builder.Append(nanos.ToString("d9", CultureInfo.InvariantCulture));
+ }
+ }
+ }
}
}
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs
new file mode 100644
index 00000000..df1292dc
--- /dev/null
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs
@@ -0,0 +1,122 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+ // Manually-written partial class for the FieldMask well-known type.
+ public partial class FieldMask : ICustomDiagnosticMessage
+ {
+ /// <summary>
+ /// Converts a timestamp specified in seconds/nanoseconds to a string.
+ /// </summary>
+ /// <remarks>
+ /// If the value is a normalized duration in the range described in <c>field_mask.proto</c>,
+ /// <paramref name="diagnosticOnly"/> is ignored. Otherwise, if the parameter is <c>true</c>,
+ /// a JSON object with a warning is returned; if it is <c>false</c>, an <see cref="InvalidOperationException"/> is thrown.
+ /// </remarks>
+ /// <param name="paths">Paths in the field mask</param>
+ /// <param name="diagnosticOnly">Determines the handling of non-normalized values</param>
+ /// <exception cref="InvalidOperationException">The represented duration is invalid, and <paramref name="diagnosticOnly"/> is <c>false</c>.</exception>
+ internal static string ToJson(IList<string> paths, bool diagnosticOnly)
+ {
+ var firstInvalid = paths.FirstOrDefault(p => !ValidatePath(p));
+ if (firstInvalid == null)
+ {
+ var builder = new StringBuilder();
+ JsonFormatter.WriteString(builder, string.Join(",", paths.Select(JsonFormatter.ToCamelCase)));
+ return builder.ToString();
+ }
+ else
+ {
+ if (diagnosticOnly)
+ {
+ var builder = new StringBuilder();
+ builder.Append("{ \"@warning\": \"Invalid FieldMask\", \"paths\": ");
+ JsonFormatter.Default.WriteList(builder, (IList) paths);
+ builder.Append(" }");
+ return builder.ToString();
+ }
+ else
+ {
+ throw new InvalidOperationException($"Invalid field mask to be converted to JSON: {firstInvalid}");
+ }
+ }
+ }
+
+ /// <summary>
+ /// Camel-case converter with added strictness for field mask formatting.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">The field mask is invalid for JSON representation</exception>
+ private static bool ValidatePath(string input)
+ {
+ for (int i = 0; i < input.Length; i++)
+ {
+ char c = input[i];
+ if (c >= 'A' && c <= 'Z')
+ {
+ return false;
+ }
+ if (c == '_' && i < input.Length - 1)
+ {
+ char next = input[i + 1];
+ if (next < 'a' || next > 'z')
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Returns a string representation of this <see cref="FieldMask"/> for diagnostic purposes.
+ /// </summary>
+ /// <remarks>
+ /// Normally the returned value will be a JSON string value (including leading and trailing quotes) but
+ /// when the value is non-normalized or out of range, a JSON object representation will be returned
+ /// instead, including a warning. This is to avoid exceptions being thrown when trying to
+ /// diagnose problems - the regular JSON formatter will still throw an exception for non-normalized
+ /// values.
+ /// </remarks>
+ /// <returns>A string representation of this value.</returns>
+ public string ToDiagnosticString()
+ {
+ return ToJson(Paths, true);
+ }
+ }
+}
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs
index d284acd6..86998e27 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs
@@ -31,15 +31,25 @@
#endregion
using System;
+using System.Globalization;
+using System.Text;
namespace Google.Protobuf.WellKnownTypes
{
- public partial class Timestamp
+ public partial class Timestamp : ICustomDiagnosticMessage
{
private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
- private static readonly long BclSecondsAtUnixEpoch = UnixEpoch.Ticks / TimeSpan.TicksPerSecond;
- internal static readonly long UnixSecondsAtBclMinValue = -BclSecondsAtUnixEpoch;
- internal static readonly long UnixSecondsAtBclMaxValue = (DateTime.MaxValue.Ticks / TimeSpan.TicksPerSecond) - BclSecondsAtUnixEpoch;
+ // Constants determined programmatically, but then hard-coded so they can be constant expressions.
+ private const long BclSecondsAtUnixEpoch = 62135596800;
+ internal const long UnixSecondsAtBclMaxValue = 253402300799;
+ internal const long UnixSecondsAtBclMinValue = -BclSecondsAtUnixEpoch;
+ internal const int MaxNanos = Duration.NanosecondsPerSecond - 1;
+
+ private static bool IsNormalized(long seconds, int nanoseconds) =>
+ nanoseconds >= 0 &&
+ nanoseconds <= MaxNanos &&
+ seconds >= UnixSecondsAtBclMinValue &&
+ seconds <= UnixSecondsAtBclMaxValue;
/// <summary>
/// Returns the difference between one <see cref="Timestamp"/> and another, as a <see cref="Duration"/>.
@@ -99,8 +109,14 @@ namespace Google.Protobuf.WellKnownTypes
/// <see cref="DateTime"/> value precisely on a second.
/// </remarks>
/// <returns>This timestamp as a <c>DateTime</c>.</returns>
+ /// <exception cref="InvalidOperationException">The timestamp contains invalid values; either it is
+ /// incorrectly normalized or is outside the valid range.</exception>
public DateTime ToDateTime()
{
+ if (!IsNormalized(Seconds, Nanos))
+ {
+ throw new InvalidOperationException(@"Timestamp contains invalid values: Seconds={Seconds}; Nanos={Nanos}");
+ }
return UnixEpoch.AddSeconds(Seconds).AddTicks(Nanos / Duration.NanosecondsPerTick);
}
@@ -114,6 +130,8 @@ namespace Google.Protobuf.WellKnownTypes
/// <see cref="DateTimeOffset"/> value precisely on a second.
/// </remarks>
/// <returns>This timestamp as a <c>DateTimeOffset</c>.</returns>
+ /// <exception cref="InvalidOperationException">The timestamp contains invalid values; either it is
+ /// incorrectly normalized or is outside the valid range.</exception>
public DateTimeOffset ToDateTimeOffset()
{
return new DateTimeOffset(ToDateTime(), TimeSpan.Zero);
@@ -165,5 +183,59 @@ namespace Google.Protobuf.WellKnownTypes
}
return new Timestamp { Seconds = seconds, Nanos = nanoseconds };
}
+
+ /// <summary>
+ /// Converts a timestamp specified in seconds/nanoseconds to a string.
+ /// </summary>
+ /// <remarks>
+ /// If the value is a normalized duration in the range described in <c>timestamp.proto</c>,
+ /// <paramref name="diagnosticOnly"/> is ignored. Otherwise, if the parameter is <c>true</c>,
+ /// a JSON object with a warning is returned; if it is <c>false</c>, an <see cref="InvalidOperationException"/> is thrown.
+ /// </remarks>
+ /// <param name="seconds">Seconds portion of the duration.</param>
+ /// <param name="nanoseconds">Nanoseconds portion of the duration.</param>
+ /// <param name="diagnosticOnly">Determines the handling of non-normalized values</param>
+ /// <exception cref="InvalidOperationException">The represented duration is invalid, and <paramref name="diagnosticOnly"/> is <c>false</c>.</exception>
+ internal static string ToJson(long seconds, int nanoseconds, bool diagnosticOnly)
+ {
+ if (IsNormalized(seconds, nanoseconds))
+ {
+ // Use .NET's formatting for the value down to the second, including an opening double quote (as it's a string value)
+ DateTime dateTime = UnixEpoch.AddSeconds(seconds);
+ var builder = new StringBuilder();
+ builder.Append('"');
+ builder.Append(dateTime.ToString("yyyy'-'MM'-'dd'T'HH:mm:ss", CultureInfo.InvariantCulture));
+ Duration.AppendNanoseconds(builder, nanoseconds);
+ builder.Append("Z\"");
+ return builder.ToString();
+ }
+ if (diagnosticOnly)
+ {
+ return string.Format(CultureInfo.InvariantCulture,
+ "{{ \"@warning\": \"Invalid Timestamp\", \"seconds\": \"{0}\", \"nanos\": {1} }}",
+ seconds,
+ nanoseconds);
+ }
+ else
+ {
+ throw new InvalidOperationException("Non-normalized timestamp value");
+ }
+ }
+
+ /// <summary>
+ /// Returns a string representation of this <see cref="Timestamp"/> for diagnostic purposes.
+ /// </summary>
+ /// <remarks>
+ /// Normally the returned value will be a JSON string value (including leading and trailing quotes) but
+ /// when the value is non-normalized or out of range, a JSON object representation will be returned
+ /// instead, including a warning. This is to avoid exceptions being thrown when trying to
+ /// diagnose problems - the regular JSON formatter will still throw an exception for non-normalized
+ /// values.
+ /// </remarks>
+ /// <returns>A string representation of this value.</returns>
+ public string ToDiagnosticString()
+ {
+ return ToJson(Seconds, Nanos, true);
+ }
}
}
diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh
index cd906896..44006b2c 100755
--- a/generate_descriptor_proto.sh
+++ b/generate_descriptor_proto.sh
@@ -10,6 +10,8 @@
# to make when building protoc. This is particularly useful for passing
# -j4 to run 4 jobs simultaneously.
+set -e
+
if test ! -e src/google/protobuf/stubs/common.h; then
cat >&2 << __EOF__
Could not find source code. Make sure you are running this script from the
@@ -43,51 +45,48 @@ declare -a RUNTIME_PROTO_FILES=(\
CORE_PROTO_IS_CORRECT=0
PROCESS_ROUND=1
+TMP=$(mktemp -d)
echo "Updating descriptor protos..."
while [ $CORE_PROTO_IS_CORRECT -ne 1 ]
do
echo "Round $PROCESS_ROUND"
CORE_PROTO_IS_CORRECT=1
- for PROTO_FILE in ${RUNTIME_PROTO_FILES[@]}; do
- BASE_NAME=${PROTO_FILE%.*}
- cp ${BASE_NAME}.pb.h ${BASE_NAME}.pb.h.tmp
- cp ${BASE_NAME}.pb.cc ${BASE_NAME}.pb.cc.tmp
- done
- cp google/protobuf/compiler/plugin.pb.h google/protobuf/compiler/plugin.pb.h.tmp
- cp google/protobuf/compiler/plugin.pb.cc google/protobuf/compiler/plugin.pb.cc.tmp
make $@ protoc &&
- ./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:. ${RUNTIME_PROTO_FILES[@]} && \
- ./protoc --cpp_out=dllexport_decl=LIBPROTOC_EXPORT:. google/protobuf/compiler/plugin.proto
+ ./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:$TMP ${RUNTIME_PROTO_FILES[@]} && \
+ ./protoc --cpp_out=dllexport_decl=LIBPROTOC_EXPORT:$TMP google/protobuf/compiler/plugin.proto
for PROTO_FILE in ${RUNTIME_PROTO_FILES[@]}; do
BASE_NAME=${PROTO_FILE%.*}
- diff ${BASE_NAME}.pb.h ${BASE_NAME}.pb.h.tmp > /dev/null
+ diff ${BASE_NAME}.pb.h $TMP/${BASE_NAME}.pb.h > /dev/null
if test $? -ne 0; then
CORE_PROTO_IS_CORRECT=0
fi
- diff ${BASE_NAME}.pb.cc ${BASE_NAME}.pb.cc.tmp > /dev/null
+ diff ${BASE_NAME}.pb.cc $TMP/${BASE_NAME}.pb.cc > /dev/null
if test $? -ne 0; then
CORE_PROTO_IS_CORRECT=0
fi
done
- diff google/protobuf/compiler/plugin.pb.h google/protobuf/compiler/plugin.pb.h.tmp > /dev/null
+ diff google/protobuf/compiler/plugin.pb.h $TMP/google/protobuf/compiler/plugin.pb.h > /dev/null
if test $? -ne 0; then
CORE_PROTO_IS_CORRECT=0
fi
- diff google/protobuf/compiler/plugin.pb.cc google/protobuf/compiler/plugin.pb.cc.tmp > /dev/null
+ diff google/protobuf/compiler/plugin.pb.cc $TMP/google/protobuf/compiler/plugin.pb.cc > /dev/null
if test $? -ne 0; then
CORE_PROTO_IS_CORRECT=0
fi
- for PROTO_FILE in ${RUNTIME_PROTO_FILES[@]}; do
- BASE_NAME=${PROTO_FILE%.*}
- rm ${BASE_NAME}.pb.h.tmp
- rm ${BASE_NAME}.pb.cc.tmp
- done
- rm google/protobuf/compiler/plugin.pb.h.tmp
- rm google/protobuf/compiler/plugin.pb.cc.tmp
+ # Only override the output if the files are different to avoid re-compilation
+ # of the protoc.
+ if [ $CORE_PROTO_IS_CORRECT -ne 1 ]; then
+ for PROTO_FILE in ${RUNTIME_PROTO_FILES[@]}; do
+ BASE_NAME=${PROTO_FILE%.*}
+ mv $TMP/${BASE_NAME}.pb.h ${BASE_NAME}.pb.h
+ mv $TMP/${BASE_NAME}.pb.cc ${BASE_NAME}.pb.cc
+ done
+ mv $TMP/google/protobuf/compiler/plugin.pb.* google/protobuf/compiler/
+ fi
PROCESS_ROUND=$((PROCESS_ROUND + 1))
done
diff --git a/java/core/src/main/java/com/google/protobuf/BoundedByteString.java b/java/core/src/main/java/com/google/protobuf/BoundedByteString.java
deleted file mode 100644
index 934c9030..00000000
--- a/java/core/src/main/java/com/google/protobuf/BoundedByteString.java
+++ /dev/null
@@ -1,124 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf;
-
-import java.io.IOException;
-import java.io.InvalidObjectException;
-import java.io.ObjectInputStream;
-
-/**
- * This class is used to represent the substring of a {@link ByteString} over a
- * single byte array. In terms of the public API of {@link ByteString}, you end
- * up here by calling {@link ByteString#copyFrom(byte[])} followed by {@link
- * ByteString#substring(int, int)}.
- *
- * <p>This class contains most of the overhead involved in creating a substring
- * from a {@link LiteralByteString}. The overhead involves some range-checking
- * and two extra fields.
- *
- * @author carlanton@google.com (Carl Haverl)
- */
-final class BoundedByteString extends LiteralByteString {
-
- private final int bytesOffset;
- private final int bytesLength;
-
- /**
- * Creates a {@code BoundedByteString} backed by the sub-range of given array,
- * without copying.
- *
- * @param bytes array to wrap
- * @param offset index to first byte to use in bytes
- * @param length number of bytes to use from bytes
- * @throws IllegalArgumentException if {@code offset < 0}, {@code length < 0},
- * or if {@code offset + length >
- * bytes.length}.
- */
- BoundedByteString(byte[] bytes, int offset, int length) {
- super(bytes);
- checkRange(offset, offset + length, bytes.length);
-
- this.bytesOffset = offset;
- this.bytesLength = length;
- }
-
- /**
- * Gets the byte at the given index.
- * Throws {@link ArrayIndexOutOfBoundsException}
- * for backwards-compatibility reasons although it would more properly be
- * {@link IndexOutOfBoundsException}.
- *
- * @param index index of byte
- * @return the value
- * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
- */
- @Override
- public byte byteAt(int index) {
- // We must check the index ourselves as we cannot rely on Java array index
- // checking for substrings.
- checkIndex(index, size());
- return bytes[bytesOffset + index];
- }
-
- @Override
- public int size() {
- return bytesLength;
- }
-
- @Override
- protected int getOffsetIntoBytes() {
- return bytesOffset;
- }
-
- // =================================================================
- // ByteString -> byte[]
-
- @Override
- protected void copyToInternal(byte[] target, int sourceOffset, int targetOffset,
- int numberToCopy) {
- System.arraycopy(bytes, getOffsetIntoBytes() + sourceOffset, target,
- targetOffset, numberToCopy);
- }
-
- // =================================================================
- // Serializable
-
- private static final long serialVersionUID = 1L;
-
- Object writeReplace() {
- return new LiteralByteString(toByteArray());
- }
-
- private void readObject(@SuppressWarnings("unused") ObjectInputStream in) throws IOException {
- throw new InvalidObjectException(
- "BoundedByteStream instances are not to be serialized directly");
- }
-}
diff --git a/java/core/src/main/java/com/google/protobuf/ByteString.java b/java/core/src/main/java/com/google/protobuf/ByteString.java
index 68f20d51..305236f3 100644
--- a/java/core/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/core/src/main/java/com/google/protobuf/ByteString.java
@@ -1,38 +1,13 @@
-// 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.
+// Copyright 2007 Google Inc. All rights reserved.
package com.google.protobuf;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
@@ -41,6 +16,7 @@ import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
@@ -81,7 +57,7 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
/**
* Empty {@code ByteString}.
*/
- public static final ByteString EMPTY = new LiteralByteString(new byte[0]);
+ public static final ByteString EMPTY = new LiteralByteString(Internal.EMPTY_BYTE_ARRAY);
/**
* Cached hash value. Intentionally accessed via a data race, which
@@ -258,6 +234,24 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
public static ByteString copyFrom(byte[] bytes) {
return copyFrom(bytes, 0, bytes.length);
}
+
+ /**
+ * Wraps the given bytes into a {@code ByteString}. Intended for internal only
+ * usage to force a classload of ByteString before LiteralByteString.
+ */
+ static ByteString wrap(byte[] bytes) {
+ // TODO(dweis): Return EMPTY when bytes are empty to reduce allocations?
+ return new LiteralByteString(bytes);
+ }
+
+ /**
+ * Wraps the given bytes into a {@code ByteString}. Intended for internal only
+ * usage to force a classload of ByteString before BoundedByteString and
+ * LiteralByteString.
+ */
+ static ByteString wrap(byte[] bytes, int offset, int length) {
+ return new BoundedByteString(bytes, offset, length);
+ }
/**
* Copies the next {@code size} bytes from a {@code java.nio.ByteBuffer} into
@@ -1149,4 +1143,314 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
return String.format("<ByteString@%s size=%d>",
Integer.toHexString(System.identityHashCode(this)), size());
}
+
+ /**
+ * This class implements a {@link com.google.protobuf.ByteString} backed by a
+ * single array of bytes, contiguous in memory. It supports substring by
+ * pointing to only a sub-range of the underlying byte array, meaning that a
+ * substring will reference the full byte-array of the string it's made from,
+ * exactly as with {@link String}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+ // Keep this class private to avoid deadlocks in classloading across threads as ByteString's
+ // static initializer loads LiteralByteString and another thread loads LiteralByteString.
+ private static class LiteralByteString extends ByteString.LeafByteString {
+ private static final long serialVersionUID = 1L;
+
+ protected final byte[] bytes;
+
+ /**
+ * Creates a {@code LiteralByteString} backed by the given array, without
+ * copying.
+ *
+ * @param bytes array to wrap
+ */
+ LiteralByteString(byte[] bytes) {
+ this.bytes = bytes;
+ }
+
+ @Override
+ public byte byteAt(int index) {
+ // Unlike most methods in this class, this one is a direct implementation
+ // ignoring the potential offset because we need to do range-checking in the
+ // substring case anyway.
+ return bytes[index];
+ }
+
+ @Override
+ public int size() {
+ return bytes.length;
+ }
+
+ // =================================================================
+ // ByteString -> substring
+
+ @Override
+ public final ByteString substring(int beginIndex, int endIndex) {
+ final int length = checkRange(beginIndex, endIndex, size());
+
+ if (length == 0) {
+ return ByteString.EMPTY;
+ }
+
+ return new BoundedByteString(bytes, getOffsetIntoBytes() + beginIndex, length);
+ }
+
+ // =================================================================
+ // ByteString -> byte[]
+
+ @Override
+ protected void copyToInternal(
+ byte[] target, int sourceOffset, int targetOffset, int numberToCopy) {
+ // Optimized form, not for subclasses, since we don't call
+ // getOffsetIntoBytes() or check the 'numberToCopy' parameter.
+ // TODO(nathanmittler): Is not calling getOffsetIntoBytes really saving that much?
+ System.arraycopy(bytes, sourceOffset, target, targetOffset, numberToCopy);
+ }
+
+ @Override
+ public final void copyTo(ByteBuffer target) {
+ target.put(bytes, getOffsetIntoBytes(), size()); // Copies bytes
+ }
+
+ @Override
+ public final ByteBuffer asReadOnlyByteBuffer() {
+ return ByteBuffer.wrap(bytes, getOffsetIntoBytes(), size()).asReadOnlyBuffer();
+ }
+
+ @Override
+ public final List<ByteBuffer> asReadOnlyByteBufferList() {
+ return Collections.singletonList(asReadOnlyByteBuffer());
+ }
+
+ @Override
+ public final void writeTo(OutputStream outputStream) throws IOException {
+ outputStream.write(toByteArray());
+ }
+
+ @Override
+ final void writeToInternal(OutputStream outputStream, int sourceOffset, int numberToWrite)
+ throws IOException {
+ outputStream.write(bytes, getOffsetIntoBytes() + sourceOffset, numberToWrite);
+ }
+
+ @Override
+ protected final String toStringInternal(Charset charset) {
+ return new String(bytes, getOffsetIntoBytes(), size(), charset);
+ }
+
+ // =================================================================
+ // UTF-8 decoding
+
+ @Override
+ public final boolean isValidUtf8() {
+ int offset = getOffsetIntoBytes();
+ return Utf8.isValidUtf8(bytes, offset, offset + size());
+ }
+
+ @Override
+ protected final int partialIsValidUtf8(int state, int offset, int length) {
+ int index = getOffsetIntoBytes() + offset;
+ return Utf8.partialIsValidUtf8(state, bytes, index, index + length);
+ }
+
+ // =================================================================
+ // equals() and hashCode()
+
+ @Override
+ public final boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (!(other instanceof ByteString)) {
+ return false;
+ }
+
+ if (size() != ((ByteString) other).size()) {
+ return false;
+ }
+ if (size() == 0) {
+ return true;
+ }
+
+ if (other instanceof LiteralByteString) {
+ LiteralByteString otherAsLiteral = (LiteralByteString) other;
+ // If we know the hash codes and they are not equal, we know the byte
+ // strings are not equal.
+ int thisHash = peekCachedHashCode();
+ int thatHash = otherAsLiteral.peekCachedHashCode();
+ if (thisHash != 0 && thatHash != 0 && thisHash != thatHash) {
+ return false;
+ }
+
+ return equalsRange((LiteralByteString) other, 0, size());
+ } else {
+ // RopeByteString and NioByteString.
+ return other.equals(this);
+ }
+ }
+
+ /**
+ * Check equality of the substring of given length of this object starting at
+ * zero with another {@code LiteralByteString} substring starting at offset.
+ *
+ * @param other what to compare a substring in
+ * @param offset offset into other
+ * @param length number of bytes to compare
+ * @return true for equality of substrings, else false.
+ */
+ @Override
+ final boolean equalsRange(ByteString other, int offset, int length) {
+ if (length > other.size()) {
+ throw new IllegalArgumentException("Length too large: " + length + size());
+ }
+ if (offset + length > other.size()) {
+ throw new IllegalArgumentException(
+ "Ran off end of other: " + offset + ", " + length + ", " + other.size());
+ }
+
+ if (other instanceof LiteralByteString) {
+ LiteralByteString lbsOther = (LiteralByteString) other;
+ byte[] thisBytes = bytes;
+ byte[] otherBytes = lbsOther.bytes;
+ int thisLimit = getOffsetIntoBytes() + length;
+ for (
+ int thisIndex = getOffsetIntoBytes(),
+ otherIndex = lbsOther.getOffsetIntoBytes() + offset;
+ (thisIndex < thisLimit); ++thisIndex, ++otherIndex) {
+ if (thisBytes[thisIndex] != otherBytes[otherIndex]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ return other.substring(offset, offset + length).equals(substring(0, length));
+ }
+
+ @Override
+ protected final int partialHash(int h, int offset, int length) {
+ return Internal.partialHash(h, bytes, getOffsetIntoBytes() + offset, length);
+ }
+
+ // =================================================================
+ // Input stream
+
+ @Override
+ public final InputStream newInput() {
+ return new ByteArrayInputStream(bytes, getOffsetIntoBytes(), size()); // No copy
+ }
+
+ @Override
+ public final CodedInputStream newCodedInput() {
+ // We trust CodedInputStream not to modify the bytes, or to give anyone
+ // else access to them.
+ return CodedInputStream.newInstance(
+ bytes, getOffsetIntoBytes(), size(), true /* bufferIsImmutable */);
+ }
+
+ // =================================================================
+ // Internal methods
+
+ /**
+ * Offset into {@code bytes[]} to use, non-zero for substrings.
+ *
+ * @return always 0 for this class
+ */
+ protected int getOffsetIntoBytes() {
+ return 0;
+ }
+ }
+
+ /**
+ * This class is used to represent the substring of a {@link ByteString} over a
+ * single byte array. In terms of the public API of {@link ByteString}, you end
+ * up here by calling {@link ByteString#copyFrom(byte[])} followed by {@link
+ * ByteString#substring(int, int)}.
+ *
+ * <p>This class contains most of the overhead involved in creating a substring
+ * from a {@link LiteralByteString}. The overhead involves some range-checking
+ * and two extra fields.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+ // Keep this class private to avoid deadlocks in classloading across threads as ByteString's
+ // static initializer loads LiteralByteString and another thread loads BoundedByteString.
+ private static final class BoundedByteString extends LiteralByteString {
+
+ private final int bytesOffset;
+ private final int bytesLength;
+
+ /**
+ * Creates a {@code BoundedByteString} backed by the sub-range of given array,
+ * without copying.
+ *
+ * @param bytes array to wrap
+ * @param offset index to first byte to use in bytes
+ * @param length number of bytes to use from bytes
+ * @throws IllegalArgumentException if {@code offset < 0}, {@code length < 0},
+ * or if {@code offset + length >
+ * bytes.length}.
+ */
+ BoundedByteString(byte[] bytes, int offset, int length) {
+ super(bytes);
+ checkRange(offset, offset + length, bytes.length);
+
+ this.bytesOffset = offset;
+ this.bytesLength = length;
+ }
+
+ /**
+ * Gets the byte at the given index.
+ * Throws {@link ArrayIndexOutOfBoundsException}
+ * for backwards-compatibility reasons although it would more properly be
+ * {@link IndexOutOfBoundsException}.
+ *
+ * @param index index of byte
+ * @return the value
+ * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
+ */
+ @Override
+ public byte byteAt(int index) {
+ // We must check the index ourselves as we cannot rely on Java array index
+ // checking for substrings.
+ checkIndex(index, size());
+ return bytes[bytesOffset + index];
+ }
+
+ @Override
+ public int size() {
+ return bytesLength;
+ }
+
+ @Override
+ protected int getOffsetIntoBytes() {
+ return bytesOffset;
+ }
+
+ // =================================================================
+ // ByteString -> byte[]
+
+ @Override
+ protected void copyToInternal(byte[] target, int sourceOffset, int targetOffset,
+ int numberToCopy) {
+ System.arraycopy(bytes, getOffsetIntoBytes() + sourceOffset, target,
+ targetOffset, numberToCopy);
+ }
+
+ // =================================================================
+ // Serializable
+
+ private static final long serialVersionUID = 1L;
+
+ Object writeReplace() {
+ return ByteString.wrap(toByteArray());
+ }
+
+ private void readObject(@SuppressWarnings("unused") ObjectInputStream in) throws IOException {
+ throw new InvalidObjectException(
+ "BoundedByteStream instances are not to be serialized directly");
+ }
+ }
}
diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
index adc91536..b3118ee0 100644
--- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -70,7 +70,15 @@ public final class CodedInputStream {
*/
public static CodedInputStream newInstance(final byte[] buf, final int off,
final int len) {
- CodedInputStream result = new CodedInputStream(buf, off, len);
+ return newInstance(buf, off, len, false);
+ }
+
+ /**
+ * Create a new CodedInputStream wrapping the given byte array slice.
+ */
+ public static CodedInputStream newInstance(final byte[] buf, final int off,
+ final int len, boolean bufferIsImmutable) {
+ CodedInputStream result = new CodedInputStream(buf, off, len, bufferIsImmutable);
try {
// Some uses of CodedInputStream can be more efficient if they know
// exactly how many bytes are available. By pushing the end point of the
@@ -113,31 +121,6 @@ public final class CodedInputStream {
}
}
- /**
- * Create a new CodedInputStream wrapping a LiteralByteString.
- */
- static CodedInputStream newInstance(LiteralByteString byteString) {
- CodedInputStream result = new CodedInputStream(byteString);
- try {
- // Some uses of CodedInputStream can be more efficient if they know
- // exactly how many bytes are available. By pushing the end point of the
- // buffer as a limit, we allow them to get this information via
- // getBytesUntilLimit(). Pushing a limit that we know is at the end of
- // the stream can never hurt, since we can never past that point anyway.
- result.pushLimit(byteString.size());
- } catch (InvalidProtocolBufferException ex) {
- // The only reason pushLimit() might throw an exception here is if len
- // is negative. Normally pushLimit()'s parameter comes directly off the
- // wire, so it's important to catch exceptions in case of corrupt or
- // malicious data. However, in this case, we expect that len is not a
- // user-supplied value, so we can assume that it being negative indicates
- // a programming error. Therefore, throwing an unchecked exception is
- // appropriate.
- throw new IllegalArgumentException(ex);
- }
- return result;
- }
-
// -----------------------------------------------------------------
/**
@@ -506,7 +489,7 @@ public final class CodedInputStream {
// Fast path: We already have the bytes in a contiguous buffer, so
// just copy directly from it.
final ByteString result = bufferIsImmutable && enableAliasing
- ? new BoundedByteString(buffer, bufferPos, size)
+ ? ByteString.wrap(buffer, bufferPos, size)
: ByteString.copyFrom(buffer, bufferPos, size);
bufferPos += size;
return result;
@@ -514,7 +497,7 @@ public final class CodedInputStream {
return ByteString.EMPTY;
} else {
// Slow path: Build a byte array first then copy it.
- return new LiteralByteString(readRawBytesSlowPath(size));
+ return ByteString.wrap(readRawBytesSlowPath(size));
}
}
@@ -886,13 +869,13 @@ public final class CodedInputStream {
private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB
private static final int BUFFER_SIZE = 4096;
- private CodedInputStream(final byte[] buffer, final int off, final int len) {
+ private CodedInputStream(final byte[] buffer, final int off, final int len, boolean bufferIsImmutable) {
this.buffer = buffer;
bufferSize = off + len;
bufferPos = off;
totalBytesRetired = -off;
input = null;
- bufferIsImmutable = false;
+ this.bufferIsImmutable = bufferIsImmutable;
}
private CodedInputStream(final InputStream input) {
@@ -904,15 +887,6 @@ public final class CodedInputStream {
bufferIsImmutable = false;
}
- private CodedInputStream(final LiteralByteString byteString) {
- buffer = byteString.bytes;
- bufferPos = byteString.getOffsetIntoBytes();
- bufferSize = bufferPos + byteString.size();
- totalBytesRetired = -bufferPos;
- input = null;
- bufferIsImmutable = true;
- }
-
public void enableAliasing(boolean enabled) {
this.enableAliasing = enabled;
}
diff --git a/java/core/src/main/java/com/google/protobuf/ExperimentalApi.java b/java/core/src/main/java/com/google/protobuf/ExperimentalApi.java
new file mode 100644
index 00000000..6f41fb81
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/ExperimentalApi.java
@@ -0,0 +1,36 @@
+package com.google.protobuf;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates a public API that can change at any time, and has no guarantee of API stability and
+ * backward-compatibility.
+ *
+ * <p>Usage guidelines:
+ * <ol>
+ * <li>This annotation is used only on public API. Internal interfaces should not use it.</li>
+ * <li>This annotation should only be added to new APIs. Adding it to an existing API is
+ * considered API-breaking.</li>
+ * <li>Removing this annotation from an API gives it stable status.</li>
+ * </ol>
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target({
+ ElementType.ANNOTATION_TYPE,
+ ElementType.CONSTRUCTOR,
+ ElementType.FIELD,
+ ElementType.METHOD,
+ ElementType.PACKAGE,
+ ElementType.TYPE})
+@Documented
+public @interface ExperimentalApi {
+ /**
+ * Context information such as links to discussion thread, tracking issue etc.
+ */
+ String value() default "";
+}
+
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
index d84fa75c..ceb97a4e 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -36,15 +36,13 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.Descriptors.OneofDescriptor;
-import com.google.protobuf.GeneratedMessageLite.ExtendableMessage;
-import com.google.protobuf.GeneratedMessageLite.GeneratedExtension;
import java.io.IOException;
+import java.io.InputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
@@ -276,6 +274,60 @@ public abstract class GeneratedMessage extends AbstractMessage
return unknownFields.mergeFieldFrom(tag, input);
}
+ protected static <M extends Message> M parseWithIOException(Parser<M> parser, InputStream input)
+ throws IOException {
+ try {
+ return parser.parseFrom(input);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
+ protected static <M extends Message> M parseWithIOException(Parser<M> parser, InputStream input,
+ ExtensionRegistryLite extensions) throws IOException {
+ try {
+ return parser.parseFrom(input, extensions);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
+ protected static <M extends Message> M parseWithIOException(Parser<M> parser,
+ CodedInputStream input) throws IOException {
+ try {
+ return parser.parseFrom(input);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
+ protected static <M extends Message> M parseWithIOException(Parser<M> parser,
+ CodedInputStream input, ExtensionRegistryLite extensions) throws IOException {
+ try {
+ return parser.parseFrom(input, extensions);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
+ protected static <M extends Message> M parseDelimitedWithIOException(Parser<M> parser,
+ InputStream input) throws IOException {
+ try {
+ return parser.parseDelimitedFrom(input);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
+ protected static <M extends Message> M parseDelimitedWithIOException(Parser<M> parser,
+ InputStream input, ExtensionRegistryLite extensions) throws IOException {
+ try {
+ return parser.parseDelimitedFrom(input, extensions);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
@Override
public void writeTo(final CodedOutputStream output) throws IOException {
MessageReflection.writeMessageTo(this, getAllFieldsRaw(), output, false);
@@ -667,7 +719,7 @@ public abstract class GeneratedMessage extends AbstractMessage
"No map fields found in " + getClass().getName());
}
- /** Like {@link internalGetMapField} but return a mutable version. */
+ /** Like {@link #internalGetMapField} but return a mutable version. */
@SuppressWarnings({"unused", "rawtypes"})
protected MapField internalGetMutableMapField(int fieldNumber) {
// Note that we can't use descriptor names here because this method will
diff --git a/java/core/src/main/java/com/google/protobuf/Internal.java b/java/core/src/main/java/com/google/protobuf/Internal.java
index 11901998..e19b6dca 100644
--- a/java/core/src/main/java/com/google/protobuf/Internal.java
+++ b/java/core/src/main/java/com/google/protobuf/Internal.java
@@ -283,10 +283,32 @@ public class Internal {
// ByteString with the same content. This is to ensure that the generated
// hashCode() method will return the same value as the pure reflection
// based hashCode() method.
- return LiteralByteString.hashCode(bytes);
+ return Internal.hashCode(bytes, 0, bytes.length);
+ }
+
+ /**
+ * Helper method for implementing {@link LiteralByteString#hashCode()}.
+ */
+ static int hashCode(byte[] bytes, int offset, int length) {
+ // The hash code for a byte array should be the same as the hash code for a
+ // ByteString with the same content. This is to ensure that the generated
+ // hashCode() method will return the same value as the pure reflection
+ // based hashCode() method.
+ int h = Internal.partialHash(length, bytes, offset, length);
+ return h == 0 ? 1 : h;
}
/**
+ * Helper method for continuously hashing bytes.
+ */
+ static int partialHash(int h, byte[] bytes, int offset, int length) {
+ for (int i = offset; i < offset + length; i++) {
+ h = h * 31 + bytes[i];
+ }
+ return h;
+ }
+
+ /**
* Helper method for implementing {@link Message#equals(Object)} for bytes
* field.
*/
@@ -337,8 +359,7 @@ public class Internal {
public static int hashCodeByteBuffer(ByteBuffer bytes) {
if (bytes.hasArray()) {
// Fast path.
- int h = LiteralByteString.hashCode(bytes.capacity(), bytes.array(),
- bytes.arrayOffset(), bytes.capacity());
+ int h = partialHash(bytes.capacity(), bytes.array(), bytes.arrayOffset(), bytes.capacity());
return h == 0 ? 1 : h;
} else {
// Read the data into a temporary byte array before calculating the
@@ -353,7 +374,7 @@ public class Internal {
final int length = duplicated.remaining() <= bufferSize ?
duplicated.remaining() : bufferSize;
duplicated.get(buffer, 0, length);
- h = LiteralByteString.hashCode(h, buffer, 0, length);
+ h = partialHash(h, buffer, 0, length);
}
return h == 0 ? 1 : h;
}
@@ -385,7 +406,6 @@ public class Internal {
public static final CodedInputStream EMPTY_CODED_INPUT_STREAM =
CodedInputStream.newInstance(EMPTY_BYTE_ARRAY);
-
/**
* Provides an immutable view of {@code List<T>} around a {@code List<F>}.
*
diff --git a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
index 0a761052..85ce7b24 100644
--- a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
+++ b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
@@ -46,6 +46,10 @@ public class InvalidProtocolBufferException extends IOException {
super(description);
}
+ public InvalidProtocolBufferException(IOException e) {
+ super(e.getMessage(), e);
+ }
+
/**
* Attaches an unfinished message to the exception to support best-effort
* parsing in {@code Parser} interface.
@@ -66,6 +70,14 @@ public class InvalidProtocolBufferException extends IOException {
return unfinishedMessage;
}
+ /**
+ * Unwraps the underlying {@link IOException} if this exception was caused by an I/O
+ * problem. Otherwise, returns {@code this}.
+ */
+ public IOException unwrapIOException() {
+ return getCause() instanceof IOException ? (IOException) getCause() : this;
+ }
+
static InvalidProtocolBufferException truncatedMessage() {
return new InvalidProtocolBufferException(
"While parsing a protocol message, the input ended unexpectedly " +
diff --git a/java/core/src/main/java/com/google/protobuf/LiteralByteString.java b/java/core/src/main/java/com/google/protobuf/LiteralByteString.java
deleted file mode 100644
index a18c2792..00000000
--- a/java/core/src/main/java/com/google/protobuf/LiteralByteString.java
+++ /dev/null
@@ -1,267 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * This class implements a {@link com.google.protobuf.ByteString} backed by a
- * single array of bytes, contiguous in memory. It supports substring by
- * pointing to only a sub-range of the underlying byte array, meaning that a
- * substring will reference the full byte-array of the string it's made from,
- * exactly as with {@link String}.
- *
- * @author carlanton@google.com (Carl Haverl)
- */
-class LiteralByteString extends ByteString.LeafByteString {
- private static final long serialVersionUID = 1L;
-
- protected final byte[] bytes;
-
- /**
- * Creates a {@code LiteralByteString} backed by the given array, without
- * copying.
- *
- * @param bytes array to wrap
- */
- LiteralByteString(byte[] bytes) {
- this.bytes = bytes;
- }
-
- @Override
- public byte byteAt(int index) {
- // Unlike most methods in this class, this one is a direct implementation
- // ignoring the potential offset because we need to do range-checking in the
- // substring case anyway.
- return bytes[index];
- }
-
- @Override
- public int size() {
- return bytes.length;
- }
-
- // =================================================================
- // ByteString -> substring
-
- @Override
- public final ByteString substring(int beginIndex, int endIndex) {
- final int length = checkRange(beginIndex, endIndex, size());
-
- if (length == 0) {
- return ByteString.EMPTY;
- }
-
- return new BoundedByteString(bytes, getOffsetIntoBytes() + beginIndex, length);
- }
-
- // =================================================================
- // ByteString -> byte[]
-
- @Override
- protected void copyToInternal(
- byte[] target, int sourceOffset, int targetOffset, int numberToCopy) {
- // Optimized form, not for subclasses, since we don't call
- // getOffsetIntoBytes() or check the 'numberToCopy' parameter.
- // TODO(nathanmittler): Is not calling getOffsetIntoBytes really saving that much?
- System.arraycopy(bytes, sourceOffset, target, targetOffset, numberToCopy);
- }
-
- @Override
- public final void copyTo(ByteBuffer target) {
- target.put(bytes, getOffsetIntoBytes(), size()); // Copies bytes
- }
-
- @Override
- public final ByteBuffer asReadOnlyByteBuffer() {
- return ByteBuffer.wrap(bytes, getOffsetIntoBytes(), size()).asReadOnlyBuffer();
- }
-
- @Override
- public final List<ByteBuffer> asReadOnlyByteBufferList() {
- return Collections.singletonList(asReadOnlyByteBuffer());
- }
-
- @Override
- public final void writeTo(OutputStream outputStream) throws IOException {
- outputStream.write(toByteArray());
- }
-
- @Override
- final void writeToInternal(OutputStream outputStream, int sourceOffset, int numberToWrite)
- throws IOException {
- outputStream.write(bytes, getOffsetIntoBytes() + sourceOffset, numberToWrite);
- }
-
- @Override
- protected final String toStringInternal(Charset charset) {
- return new String(bytes, getOffsetIntoBytes(), size(), charset);
- }
-
- // =================================================================
- // UTF-8 decoding
-
- @Override
- public final boolean isValidUtf8() {
- int offset = getOffsetIntoBytes();
- return Utf8.isValidUtf8(bytes, offset, offset + size());
- }
-
- @Override
- protected final int partialIsValidUtf8(int state, int offset, int length) {
- int index = getOffsetIntoBytes() + offset;
- return Utf8.partialIsValidUtf8(state, bytes, index, index + length);
- }
-
- // =================================================================
- // equals() and hashCode()
-
- @Override
- public final boolean equals(Object other) {
- if (other == this) {
- return true;
- }
- if (!(other instanceof ByteString)) {
- return false;
- }
-
- if (size() != ((ByteString) other).size()) {
- return false;
- }
- if (size() == 0) {
- return true;
- }
-
- if (other instanceof LiteralByteString) {
- LiteralByteString otherAsLiteral = (LiteralByteString) other;
- // If we know the hash codes and they are not equal, we know the byte
- // strings are not equal.
- int thisHash = peekCachedHashCode();
- int thatHash = otherAsLiteral.peekCachedHashCode();
- if (thisHash != 0 && thatHash != 0 && thisHash != thatHash) {
- return false;
- }
-
- return equalsRange((LiteralByteString) other, 0, size());
- } else {
- // RopeByteString and NioByteString.
- return other.equals(this);
- }
- }
-
- /**
- * Check equality of the substring of given length of this object starting at
- * zero with another {@code LiteralByteString} substring starting at offset.
- *
- * @param other what to compare a substring in
- * @param offset offset into other
- * @param length number of bytes to compare
- * @return true for equality of substrings, else false.
- */
- @Override
- final boolean equalsRange(ByteString other, int offset, int length) {
- if (length > other.size()) {
- throw new IllegalArgumentException("Length too large: " + length + size());
- }
- if (offset + length > other.size()) {
- throw new IllegalArgumentException(
- "Ran off end of other: " + offset + ", " + length + ", " + other.size());
- }
-
- if (other instanceof LiteralByteString) {
- LiteralByteString lbsOther = (LiteralByteString) other;
- byte[] thisBytes = bytes;
- byte[] otherBytes = lbsOther.bytes;
- int thisLimit = getOffsetIntoBytes() + length;
- for (
- int thisIndex = getOffsetIntoBytes(), otherIndex = lbsOther.getOffsetIntoBytes() + offset;
- (thisIndex < thisLimit); ++thisIndex, ++otherIndex) {
- if (thisBytes[thisIndex] != otherBytes[otherIndex]) {
- return false;
- }
- }
- return true;
- }
-
- return other.substring(offset, offset + length).equals(substring(0, length));
- }
-
- @Override
- protected final int partialHash(int h, int offset, int length) {
- return hashCode(h, bytes, getOffsetIntoBytes() + offset, length);
- }
-
- static int hashCode(int h, byte[] bytes, int offset, int length) {
- for (int i = offset; i < offset + length; i++) {
- h = h * 31 + bytes[i];
- }
- return h;
- }
-
- static int hashCode(byte[] bytes) {
- int h = hashCode(bytes.length, bytes, 0, bytes.length);
- return h == 0 ? 1 : h;
- }
-
- // =================================================================
- // Input stream
-
- @Override
- public final InputStream newInput() {
- return new ByteArrayInputStream(bytes, getOffsetIntoBytes(), size()); // No copy
- }
-
- @Override
- public final CodedInputStream newCodedInput() {
- // We trust CodedInputStream not to modify the bytes, or to give anyone
- // else access to them.
- return CodedInputStream.newInstance(this);
- }
-
- // =================================================================
- // Internal methods
-
- /**
- * Offset into {@code bytes[]} to use, non-zero for substrings.
- *
- * @return always 0 for this class
- */
- protected int getOffsetIntoBytes() {
- return 0;
- }
-}
diff --git a/java/core/src/main/java/com/google/protobuf/MapFieldLite.java b/java/core/src/main/java/com/google/protobuf/MapFieldLite.java
index 16d3e6d2..960b6339 100644
--- a/java/core/src/main/java/com/google/protobuf/MapFieldLite.java
+++ b/java/core/src/main/java/com/google/protobuf/MapFieldLite.java
@@ -136,7 +136,7 @@ public final class MapFieldLite<K, V> implements MutabilityOracle {
private static int calculateHashCodeForObject(Object a) {
if (a instanceof byte[]) {
- return LiteralByteString.hashCode((byte[]) a);
+ return Internal.hashCode((byte[]) a);
}
// Enums should be stored as integers internally.
if (a instanceof EnumLite) {
diff --git a/java/core/src/main/java/com/google/protobuf/Parser.java b/java/core/src/main/java/com/google/protobuf/Parser.java
index 227c02b7..3fa11c3b 100644
--- a/java/core/src/main/java/com/google/protobuf/Parser.java
+++ b/java/core/src/main/java/com/google/protobuf/Parser.java
@@ -30,6 +30,7 @@
package com.google.protobuf;
+import java.io.IOException;
import java.io.InputStream;
/**
@@ -37,9 +38,20 @@ import java.io.InputStream;
*
* The implementation should be stateless and thread-safe.
*
+ * <p>All methods may throw {@link InvalidProtocolBufferException}. In the event of invalid data,
+ * like an encoding error, the cause of the thrown exception will be {@code null}. However, if an
+ * I/O problem occurs, an exception is thrown with an {@link IOException} cause.
+ *
* @author liujisi@google.com (Pherl Liu)
*/
public interface Parser<MessageType> {
+
+ // NB(jh): Other parts of the protobuf API that parse messages distinguish between an I/O problem
+ // (like failure reading bytes from a socket) and invalid data (encoding error) via the type of
+ // thrown exception. But it would be source-incompatible to make the methods in this interface do
+ // so since they were originally spec'ed to only throw InvalidProtocolBufferException. So callers
+ // must inspect the cause of the exception to distinguish these two cases.
+
/**
* Parses a message of {@code MessageType} from the input.
*
diff --git a/java/core/src/main/java/com/google/protobuf/RopeByteString.java b/java/core/src/main/java/com/google/protobuf/RopeByteString.java
index 6e8eb724..469c90c2 100644
--- a/java/core/src/main/java/com/google/protobuf/RopeByteString.java
+++ b/java/core/src/main/java/com/google/protobuf/RopeByteString.java
@@ -213,14 +213,14 @@ final class RopeByteString extends ByteString {
* @param right string on the right
* @return string formed by copying data bytes
*/
- private static LiteralByteString concatenateBytes(ByteString left,
+ private static ByteString concatenateBytes(ByteString left,
ByteString right) {
int leftSize = left.size();
int rightSize = right.size();
byte[] bytes = new byte[leftSize + rightSize];
left.copyTo(bytes, 0, 0, leftSize);
right.copyTo(bytes, 0, leftSize, rightSize);
- return new LiteralByteString(bytes); // Constructor wraps bytes
+ return ByteString.wrap(bytes); // Constructor wraps bytes
}
/**
@@ -735,7 +735,7 @@ final class RopeByteString extends ByteString {
private static final long serialVersionUID = 1L;
Object writeReplace() {
- return new LiteralByteString(toByteArray());
+ return ByteString.wrap(toByteArray());
}
private void readObject(@SuppressWarnings("unused") ObjectInputStream in) throws IOException {
diff --git a/java/core/src/main/java/com/google/protobuf/UnsafeByteStrings.java b/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java
index c1997515..8806395c 100644
--- a/java/core/src/main/java/com/google/protobuf/UnsafeByteStrings.java
+++ b/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java
@@ -33,15 +33,18 @@ package com.google.protobuf;
import java.nio.ByteBuffer;
/**
- * Provides unsafe factory methods for {@link ByteString} instances.
+ * Provides a number of unsafe byte operations to be used by advanced applications with high
+ * performance requirements. These methods are referred to as "unsafe" due to the fact that they
+ * potentially expose the backing buffer of a {@link ByteString} to the application.
*
* <p><strong>DISCLAIMER:</strong> The methods in this class should only be called if it is
* guaranteed that the the buffer backing the {@link ByteString} will never change! Mutation of a
* {@link ByteString} can lead to unexpected and undesirable consequences in your application,
* and will likely be difficult to debug. Proceed with caution!
*/
-public final class UnsafeByteStrings {
- private UnsafeByteStrings() {}
+@ExperimentalApi
+public final class UnsafeByteOperations {
+ private UnsafeByteOperations() {}
/**
* An unsafe operation that returns a {@link ByteString} that is backed by the provided buffer.
@@ -50,6 +53,11 @@ public final class UnsafeByteStrings {
* @return a {@link ByteString} backed by the provided buffer.
*/
public static ByteString unsafeWrap(ByteBuffer buffer) {
- return new NioByteString(buffer);
+ if (buffer.hasArray()) {
+ final int offset = buffer.arrayOffset();
+ return ByteString.wrap(buffer.array(), offset + buffer.position(), buffer.remaining());
+ } else {
+ return new NioByteString(buffer);
+ }
}
}
diff --git a/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java b/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java
index 2dfae2e6..7a8a0a5e 100644
--- a/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java
+++ b/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java
@@ -62,7 +62,7 @@ public class BoundedByteStringTest extends LiteralByteStringTest {
@Override
public void testToString() throws UnsupportedEncodingException {
String testString = "I love unicode \u1234\u5678 characters";
- LiteralByteString unicode = new LiteralByteString(testString.getBytes(Internal.UTF_8));
+ ByteString unicode = ByteString.wrap(testString.getBytes(Internal.UTF_8));
ByteString chopped = unicode.substring(2, unicode.size() - 6);
assertEquals(classUnderTest + ".substring() must have the expected type",
classUnderTest, getActualClassName(chopped));
@@ -75,7 +75,7 @@ public class BoundedByteStringTest extends LiteralByteStringTest {
@Override
public void testCharsetToString() {
String testString = "I love unicode \u1234\u5678 characters";
- LiteralByteString unicode = new LiteralByteString(testString.getBytes(Internal.UTF_8));
+ ByteString unicode = ByteString.wrap(testString.getBytes(Internal.UTF_8));
ByteString chopped = unicode.substring(2, unicode.size() - 6);
assertEquals(classUnderTest + ".substring() must have the expected type",
classUnderTest, getActualClassName(chopped));
diff --git a/java/core/src/test/java/com/google/protobuf/ByteStringTest.java b/java/core/src/test/java/com/google/protobuf/ByteStringTest.java
index 36f64251..5267c160 100644
--- a/java/core/src/test/java/com/google/protobuf/ByteStringTest.java
+++ b/java/core/src/test/java/com/google/protobuf/ByteStringTest.java
@@ -655,11 +655,11 @@ public class ByteStringTest extends TestCase {
// trees of empty leaves, to make a string that will fail this test.
for (int i = 1; i < duo.size(); ++i) {
assertTrue("Substrings of size() < 2 must not be RopeByteStrings",
- duo.substring(i - 1, i) instanceof LiteralByteString);
+ duo.substring(i - 1, i) instanceof ByteString.LeafByteString);
}
for (int i = 1; i < quintet.size(); ++i) {
assertTrue("Substrings of size() < 2 must not be RopeByteStrings",
- quintet.substring(i - 1, i) instanceof LiteralByteString);
+ quintet.substring(i - 1, i) instanceof ByteString.LeafByteString);
}
}
@@ -724,7 +724,7 @@ public class ByteStringTest extends TestCase {
}
data1[1] = (byte) 11;
// Test LiteralByteString.writeTo(OutputStream,int,int)
- LiteralByteString left = new LiteralByteString(data1);
+ ByteString left = ByteString.wrap(data1);
byte[] result = substringUsingWriteTo(left, 1, 1);
assertEquals(1, result.length);
assertEquals((byte) 11, result[0]);
@@ -733,7 +733,7 @@ public class ByteStringTest extends TestCase {
for (int i = 0; i < data1.length; i++) {
data2[i] = (byte) 2;
}
- LiteralByteString right = new LiteralByteString(data2);
+ ByteString right = ByteString.wrap(data2);
// Concatenate two ByteStrings to create a RopeByteString.
ByteString root = left.concat(right);
// Make sure we are actually testing a RopeByteString with a simple tree
diff --git a/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java
index c8495633..68b55ceb 100644
--- a/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java
+++ b/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java
@@ -75,9 +75,7 @@ public class LiteralByteStringTest extends TestCase {
}
protected String getActualClassName(Object object) {
- String actualClassName = object.getClass().getName();
- actualClassName = actualClassName.substring(actualClassName.lastIndexOf('.') + 1);
- return actualClassName;
+ return object.getClass().getSimpleName();
}
public void testByteAt() {
@@ -350,14 +348,14 @@ public class LiteralByteStringTest extends TestCase {
public void testToString() throws UnsupportedEncodingException {
String testString = "I love unicode \u1234\u5678 characters";
- LiteralByteString unicode = new LiteralByteString(testString.getBytes(Internal.UTF_8));
+ ByteString unicode = ByteString.wrap(testString.getBytes(Internal.UTF_8));
String roundTripString = unicode.toString(UTF_8);
assertEquals(classUnderTest + " unicode must match", testString, roundTripString);
}
public void testCharsetToString() {
String testString = "I love unicode \u1234\u5678 characters";
- LiteralByteString unicode = new LiteralByteString(testString.getBytes(Internal.UTF_8));
+ ByteString unicode = ByteString.wrap(testString.getBytes(Internal.UTF_8));
String roundTripString = unicode.toString(Internal.UTF_8);
assertEquals(classUnderTest + " unicode must match", testString, roundTripString);
}
@@ -365,7 +363,7 @@ public class LiteralByteStringTest extends TestCase {
public void testToString_returnsCanonicalEmptyString() {
assertSame(classUnderTest + " must be the same string references",
ByteString.EMPTY.toString(Internal.UTF_8),
- new LiteralByteString(new byte[]{}).toString(Internal.UTF_8));
+ ByteString.wrap(new byte[]{}).toString(Internal.UTF_8));
}
public void testToString_raisesException() {
@@ -377,7 +375,7 @@ public class LiteralByteStringTest extends TestCase {
}
try {
- new LiteralByteString(referenceBytes).toString("invalid");
+ ByteString.wrap(referenceBytes).toString("invalid");
fail("Should have thrown an exception.");
} catch (UnsupportedEncodingException expected) {
// This is success
@@ -390,15 +388,15 @@ public class LiteralByteStringTest extends TestCase {
assertFalse(classUnderTest + " must not equal the empty string",
stringUnderTest.equals(ByteString.EMPTY));
assertEquals(classUnderTest + " empty strings must be equal",
- new LiteralByteString(new byte[]{}), stringUnderTest.substring(55, 55));
+ ByteString.wrap(new byte[]{}), stringUnderTest.substring(55, 55));
assertEquals(classUnderTest + " must equal another string with the same value",
- stringUnderTest, new LiteralByteString(referenceBytes));
+ stringUnderTest, ByteString.wrap(referenceBytes));
byte[] mungedBytes = new byte[referenceBytes.length];
System.arraycopy(referenceBytes, 0, mungedBytes, 0, referenceBytes.length);
mungedBytes[mungedBytes.length - 5] = (byte) (mungedBytes[mungedBytes.length - 5] ^ 0xFF);
assertFalse(classUnderTest + " must not equal every string with the same length",
- stringUnderTest.equals(new LiteralByteString(mungedBytes)));
+ stringUnderTest.equals(ByteString.wrap(mungedBytes)));
}
public void testHashCode() {
diff --git a/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java b/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java
index 0679937f..e40a3662 100644
--- a/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java
+++ b/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java
@@ -52,13 +52,12 @@ import java.util.NoSuchElementException;
* Tests for {@link NioByteString}.
*/
public class NioByteStringTest extends TestCase {
- private static final ByteString EMPTY = UnsafeByteStrings.unsafeWrap(
- ByteBuffer.wrap(new byte[0]));
+ private static final ByteString EMPTY = new NioByteString(ByteBuffer.wrap(new byte[0]));
private static final String CLASSNAME = NioByteString.class.getSimpleName();
private static final byte[] BYTES = ByteStringTest.getTestBytes(1234, 11337766L);
- private static final int EXPECTED_HASH = new LiteralByteString(BYTES).hashCode();
+ private static final int EXPECTED_HASH = ByteString.wrap(BYTES).hashCode();
private static final ByteBuffer BUFFER = ByteBuffer.wrap(BYTES.clone());
- private static final ByteString TEST_STRING = UnsafeByteStrings.unsafeWrap(BUFFER);
+ private static final ByteString TEST_STRING = new NioByteString(BUFFER);
public void testExpectedType() {
String actualClassName = getActualClassName(TEST_STRING);
@@ -362,7 +361,7 @@ public class NioByteStringTest extends TestCase {
public void testToString_returnsCanonicalEmptyString() {
assertSame(CLASSNAME + " must be the same string references",
EMPTY.toString(UTF_8),
- UnsafeByteStrings.unsafeWrap(ByteBuffer.wrap(new byte[0])).toString(UTF_8));
+ new NioByteString(ByteBuffer.wrap(new byte[0])).toString(UTF_8));
}
public void testToString_raisesException() {
@@ -389,11 +388,11 @@ public class NioByteStringTest extends TestCase {
assertEquals(CLASSNAME + " empty strings must be equal",
EMPTY, TEST_STRING.substring(55, 55));
assertEquals(CLASSNAME + " must equal another string with the same value",
- TEST_STRING, UnsafeByteStrings.unsafeWrap(BUFFER));
+ TEST_STRING, new NioByteString(BUFFER));
byte[] mungedBytes = mungedBytes();
assertFalse(CLASSNAME + " must not equal every string with the same length",
- TEST_STRING.equals(UnsafeByteStrings.unsafeWrap(ByteBuffer.wrap(mungedBytes))));
+ TEST_STRING.equals(new NioByteString(ByteBuffer.wrap(mungedBytes))));
}
public void testEqualsLiteralByteString() {
@@ -451,7 +450,7 @@ public class NioByteStringTest extends TestCase {
}
public void testPeekCachedHashCode() {
- ByteString newString = UnsafeByteStrings.unsafeWrap(BUFFER);
+ ByteString newString = new NioByteString(BUFFER);
assertEquals(CLASSNAME + ".peekCachedHashCode() should return zero at first", 0,
newString.peekCachedHashCode());
newString.hashCode();
@@ -541,6 +540,6 @@ public class NioByteStringTest extends TestCase {
}
private static ByteString forString(String str) {
- return UnsafeByteStrings.unsafeWrap(ByteBuffer.wrap(str.getBytes(UTF_8)));
+ return new NioByteString(ByteBuffer.wrap(str.getBytes(UTF_8)));
}
}
diff --git a/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java b/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java
new file mode 100644
index 00000000..37fa242d
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java
@@ -0,0 +1,211 @@
+package com.google.protobuf;
+
+import com.google.protobuf.DescriptorProtos.DescriptorProto;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Tests the exceptions thrown when parsing from a stream. The methods on the {@link Parser}
+ * interface are specified to only throw {@link InvalidProtocolBufferException}. But we really want
+ * to distinguish between invalid protos vs. actual I/O errors (like failures reading from a
+ * socket, etc.). So, when we're not using the parser directly, an {@link IOException} should be
+ * thrown where appropriate, instead of always an {@link InvalidProtocolBufferException}.
+ *
+ * @author jh@squareup.com (Joshua Humphries)
+ */
+public class ParseExceptionsTest {
+
+ private interface ParseTester {
+ DescriptorProto parse(InputStream in) throws IOException;
+ }
+
+ private byte serializedProto[];
+
+ private void setup() {
+ serializedProto = DescriptorProto.getDescriptor().toProto().toByteArray();
+ }
+
+ private void setupDelimited() {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ try {
+ DescriptorProto.getDescriptor().toProto().writeDelimitedTo(bos);
+ } catch (IOException e) {
+ fail("Exception not expected: " + e);
+ }
+ serializedProto = bos.toByteArray();
+ }
+
+ @Test public void message_parseFrom_InputStream() {
+ setup();
+ verifyExceptions(new ParseTester() {
+ public DescriptorProto parse(InputStream in) throws IOException {
+ return DescriptorProto.parseFrom(in);
+ }
+ });
+ }
+
+ @Test public void message_parseFrom_InputStreamAndExtensionRegistry() {
+ setup();
+ verifyExceptions(new ParseTester() {
+ public DescriptorProto parse(InputStream in) throws IOException {
+ return DescriptorProto.parseFrom(in, ExtensionRegistry.newInstance());
+ }
+ });
+ }
+
+ @Test public void message_parseFrom_CodedInputStream() {
+ setup();
+ verifyExceptions(new ParseTester() {
+ public DescriptorProto parse(InputStream in) throws IOException {
+ return DescriptorProto.parseFrom(CodedInputStream.newInstance(in));
+ }
+ });
+ }
+
+ @Test public void message_parseFrom_CodedInputStreamAndExtensionRegistry() {
+ setup();
+ verifyExceptions(new ParseTester() {
+ public DescriptorProto parse(InputStream in) throws IOException {
+ return DescriptorProto.parseFrom(CodedInputStream.newInstance(in),
+ ExtensionRegistry.newInstance());
+ }
+ });
+ }
+
+ @Test public void message_parseDelimitedFrom_InputStream() {
+ setupDelimited();
+ verifyExceptions(new ParseTester() {
+ public DescriptorProto parse(InputStream in) throws IOException {
+ return DescriptorProto.parseDelimitedFrom(in);
+ }
+ });
+ }
+
+ @Test public void message_parseDelimitedFrom_InputStreamAndExtensionRegistry() {
+ setupDelimited();
+ verifyExceptions(new ParseTester() {
+ public DescriptorProto parse(InputStream in) throws IOException {
+ return DescriptorProto.parseDelimitedFrom(in, ExtensionRegistry.newInstance());
+ }
+ });
+ }
+
+ @Test public void messageBuilder_mergeFrom_InputStream() {
+ setup();
+ verifyExceptions(new ParseTester() {
+ public DescriptorProto parse(InputStream in) throws IOException {
+ return DescriptorProto.newBuilder().mergeFrom(in).build();
+ }
+ });
+ }
+
+ @Test public void messageBuilder_mergeFrom_InputStreamAndExtensionRegistry() {
+ setup();
+ verifyExceptions(new ParseTester() {
+ public DescriptorProto parse(InputStream in) throws IOException {
+ return DescriptorProto.newBuilder().mergeFrom(in, ExtensionRegistry.newInstance()).build();
+ }
+ });
+ }
+
+ @Test public void messageBuilder_mergeFrom_CodedInputStream() {
+ setup();
+ verifyExceptions(new ParseTester() {
+ public DescriptorProto parse(InputStream in) throws IOException {
+ return DescriptorProto.newBuilder().mergeFrom(CodedInputStream.newInstance(in)).build();
+ }
+ });
+ }
+
+ @Test public void messageBuilder_mergeFrom_CodedInputStreamAndExtensionRegistry() {
+ setup();
+ verifyExceptions(new ParseTester() {
+ public DescriptorProto parse(InputStream in) throws IOException {
+ return DescriptorProto.newBuilder()
+ .mergeFrom(CodedInputStream.newInstance(in), ExtensionRegistry.newInstance()).build();
+ }
+ });
+ }
+
+ @Test public void messageBuilder_mergeDelimitedFrom_InputStream() {
+ setupDelimited();
+ verifyExceptions(new ParseTester() {
+ public DescriptorProto parse(InputStream in) throws IOException {
+ DescriptorProto.Builder builder = DescriptorProto.newBuilder();
+ builder.mergeDelimitedFrom(in);
+ return builder.build();
+ }
+ });
+ }
+
+ @Test public void messageBuilder_mergeDelimitedFrom_InputStreamAndExtensionRegistry() {
+ setupDelimited();
+ verifyExceptions(new ParseTester() {
+ public DescriptorProto parse(InputStream in) throws IOException {
+ DescriptorProto.Builder builder = DescriptorProto.newBuilder();
+ builder.mergeDelimitedFrom(in, ExtensionRegistry.newInstance());
+ return builder.build();
+ }
+ });
+ }
+
+ private void verifyExceptions(ParseTester parseTester) {
+ // No exception
+ try {
+ assertEquals(DescriptorProto.getDescriptor().toProto(),
+ parseTester.parse(new ByteArrayInputStream(serializedProto)));
+ } catch (IOException e) {
+ fail("No exception expected: " + e);
+ }
+
+ // IOException
+ try {
+ // using a "broken" stream that will throw part-way through reading the message
+ parseTester.parse(broken(new ByteArrayInputStream(serializedProto)));
+ fail("IOException expected but not thrown");
+ } catch (IOException e) {
+ assertFalse(e instanceof InvalidProtocolBufferException);
+ }
+
+ // InvalidProtocolBufferException
+ try {
+ // make the serialized proto invalid
+ for (int i = 0; i < 50; i++) {
+ serializedProto[i] = -1;
+ }
+ parseTester.parse(new ByteArrayInputStream(serializedProto));
+ fail("InvalidProtocolBufferException expected but not thrown");
+ } catch (IOException e) {
+ assertTrue(e instanceof InvalidProtocolBufferException);
+ }
+ }
+
+ private InputStream broken(InputStream i) {
+ return new FilterInputStream(i) {
+ int count = 0;
+
+ @Override public int read() throws IOException {
+ if (count++ >= 50) {
+ throw new IOException("I'm broken!");
+ }
+ return super.read();
+ }
+
+ @Override public int read(byte b[], int off, int len) throws IOException {
+ if ((count += len) >= 50) {
+ throw new IOException("I'm broken!");
+ }
+ return super.read(b, off, len);
+ }
+ };
+ }
+}
diff --git a/java/lite/pom.xml b/java/lite/pom.xml
index 29d8c8c4..70c7d047 100644
--- a/java/lite/pom.xml
+++ b/java/lite/pom.xml
@@ -84,7 +84,6 @@
<include>**/AbstractMessageLite.java</include>
<include>**/AbstractParser.java</include>
<include>**/AbstractProtobufList.java</include>
- <include>**/BoundedByteString.java</include>
<include>**/BooleanArrayList.java</include>
<include>**/ByteString.java</include>
<include>**/CodedInputStream.java</include>
@@ -101,7 +100,6 @@
<include>**/LazyFieldLite.java</include>
<include>**/LazyStringArrayList.java</include>
<include>**/LazyStringList.java</include>
- <include>**/LiteralByteString.java</include>
<include>**/LongArrayList.java</include>
<include>**/MapEntryLite.java</include>
<include>**/MapFieldLite.java</include>
@@ -119,7 +117,7 @@
<include>**/UninitializedMessageException.java</include>
<include>**/UnknownFieldSetLite.java</include>
<include>**/UnmodifiableLazyStringList.java</include>
- <include>**/UnsafeByteStrings.java</include>
+ <include>**/UnsafeByteOperations.java</include>
<include>**/Utf8.java</include>
<include>**/WireFormat.java</include>
</includes>
diff --git a/m4/acx_check_suncc.m4 b/m4/acx_check_suncc.m4
index 89185932..8bc0a890 100644
--- a/m4/acx_check_suncc.m4
+++ b/m4/acx_check_suncc.m4
@@ -42,7 +42,6 @@ AC_DEFUN([ACX_CHECK_SUNCC],[
AS_IF([test "x$ac_enable_64bit" = "xyes"],[
- AC_DEFINE([SOLARIS_64BIT_ENABLED], [1], [64bit enabled])
AS_IF([test "x$libdir" = "x\${exec_prefix}/lib"],[
dnl The user hasn't overridden the default libdir, so we'll
dnl the dir suffix to match solaris 32/64-bit policy
@@ -52,17 +51,13 @@ AC_DEFUN([ACX_CHECK_SUNCC],[
dnl This should just be set in CPPFLAGS and in LDFLAGS, but libtool
dnl does the wrong thing if you don't put it into CXXFLAGS. sigh.
dnl (It also needs it in CFLAGS, or it does a different wrong thing!)
- AS_IF([test "x${ac_cv_env_CXXFLAGS_set}" = "x"],[
- CXXFLAGS="${CXXFLAGS} -m64"
- ac_cv_env_CXXFLAGS_set=set
- ac_cv_env_CXXFLAGS_value='-m64'
- ])
+ CXXFLAGS="${CXXFLAGS} -m64"
+ ac_cv_env_CXXFLAGS_set=set
+ ac_cv_env_CXXFLAGS_value='-m64'
- AS_IF([test "x${ac_cv_env_CFLAGS_set}" = "x"],[
- CFLAGS="${CFLAGS} -m64"
- ac_cv_env_CFLAGS_set=set
- ac_cv_env_CFLAGS_value='-m64'
- ])
+ CFLAGS="${CFLAGS} -m64"
+ ac_cv_env_CFLAGS_set=set
+ ac_cv_env_CFLAGS_value='-m64'
AS_IF([test "$target_cpu" = "sparc" -a "x$SUNCC" = "xyes" ],[
CXXFLAGS="-xmemalign=8s ${CXXFLAGS}"
diff --git a/objectivec/google/protobuf/Descriptor.pbobjc.h b/objectivec/google/protobuf/Descriptor.pbobjc.h
index f04616c3..9c43cfd2 100644
--- a/objectivec/google/protobuf/Descriptor.pbobjc.h
+++ b/objectivec/google/protobuf/Descriptor.pbobjc.h
@@ -1153,6 +1153,58 @@ typedef GPB_ENUM(GPBSourceCodeInfo_Location_FieldNumber) {
@end
+#pragma mark - GPBGeneratedCodeInfo
+
+typedef GPB_ENUM(GPBGeneratedCodeInfo_FieldNumber) {
+ GPBGeneratedCodeInfo_FieldNumber_AnnotationArray = 1,
+};
+
+// Describes the relationship between generated code and its original source
+// file. A GeneratedCodeInfo message is associated with only one generated
+// source file, but may contain references to different source .proto files.
+@interface GPBGeneratedCodeInfo : GPBMessage
+
+// An Annotation connects some span of text in generated code to an element
+// of its generating .proto file.
+// |annotationArray| contains |GPBGeneratedCodeInfo_Annotation|
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *annotationArray;
+@property(nonatomic, readonly) NSUInteger annotationArray_Count;
+
+@end
+
+#pragma mark - GPBGeneratedCodeInfo_Annotation
+
+typedef GPB_ENUM(GPBGeneratedCodeInfo_Annotation_FieldNumber) {
+ GPBGeneratedCodeInfo_Annotation_FieldNumber_PathArray = 1,
+ GPBGeneratedCodeInfo_Annotation_FieldNumber_SourceFile = 2,
+ GPBGeneratedCodeInfo_Annotation_FieldNumber_Begin = 3,
+ GPBGeneratedCodeInfo_Annotation_FieldNumber_End = 4,
+};
+
+@interface GPBGeneratedCodeInfo_Annotation : GPBMessage
+
+// Identifies the element in the original source .proto file. This field
+// is formatted the same as SourceCodeInfo.Location.path.
+@property(nonatomic, readwrite, strong, null_resettable) GPBInt32Array *pathArray;
+@property(nonatomic, readonly) NSUInteger pathArray_Count;
+
+// Identifies the filesystem path to the original source .proto.
+@property(nonatomic, readwrite) BOOL hasSourceFile;
+@property(nonatomic, readwrite, copy, null_resettable) NSString *sourceFile;
+
+// Identifies the starting offset in bytes in the generated code
+// that relates to the identified object.
+@property(nonatomic, readwrite) BOOL hasBegin;
+@property(nonatomic, readwrite) int32_t begin;
+
+// Identifies the ending offset in bytes in the generated code that
+// relates to the identified offset. The end offset should be one past
+// the last relevant byte (so the length of the text = end - begin).
+@property(nonatomic, readwrite) BOOL hasEnd;
+@property(nonatomic, readwrite) int32_t end;
+
+@end
+
NS_ASSUME_NONNULL_END
CF_EXTERN_C_END
diff --git a/objectivec/google/protobuf/Descriptor.pbobjc.m b/objectivec/google/protobuf/Descriptor.pbobjc.m
index e3e44c48..40309893 100644
--- a/objectivec/google/protobuf/Descriptor.pbobjc.m
+++ b/objectivec/google/protobuf/Descriptor.pbobjc.m
@@ -1434,7 +1434,11 @@ typedef struct GPBFileOptions__storage_ {
.offset = offsetof(GPBFileOptions__storage_, javananoUseDeprecatedPackage),
.defaultValue.valueBool = NO,
.dataTypeSpecific.className = NULL,
+ #if GPBOBJC_INCLUDE_FIELD_OPTIONS
+ .fieldOptions = "\000\000\000\002\030\001",
+ #else
.fieldOptions = NULL,
+ #endif // GPBOBJC_INCLUDE_FIELD_OPTIONS
},
{
.name = "uninterpretedOptionArray",
@@ -2441,5 +2445,150 @@ typedef struct GPBSourceCodeInfo_Location__storage_ {
@end
+#pragma mark - GPBGeneratedCodeInfo
+
+@implementation GPBGeneratedCodeInfo
+
+@dynamic annotationArray, annotationArray_Count;
+
+typedef struct GPBGeneratedCodeInfo__storage_ {
+ uint32_t _has_storage_[1];
+ NSMutableArray *annotationArray;
+} GPBGeneratedCodeInfo__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = nil;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "annotationArray",
+ .number = GPBGeneratedCodeInfo_FieldNumber_AnnotationArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .dataType = GPBDataTypeMessage,
+ .offset = offsetof(GPBGeneratedCodeInfo__storage_, annotationArray),
+ .defaultValue.valueMessage = nil,
+ .dataTypeSpecific.className = GPBStringifySymbol(GPBGeneratedCodeInfo_Annotation),
+ .fieldOptions = NULL,
+ },
+ };
+ GPBDescriptor *localDescriptor =
+ [GPBDescriptor allocDescriptorForClass:[GPBGeneratedCodeInfo class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBGeneratedCodeInfo__storage_)
+ wireFormat:NO];
+ NSAssert(descriptor == nil, @"Startup recursed!");
+ descriptor = localDescriptor;
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBGeneratedCodeInfo_Annotation
+
+@implementation GPBGeneratedCodeInfo_Annotation
+
+@dynamic pathArray, pathArray_Count;
+@dynamic hasSourceFile, sourceFile;
+@dynamic hasBegin, begin;
+@dynamic hasEnd, end;
+
+typedef struct GPBGeneratedCodeInfo_Annotation__storage_ {
+ uint32_t _has_storage_[1];
+ int32_t begin;
+ int32_t end;
+ GPBInt32Array *pathArray;
+ NSString *sourceFile;
+} GPBGeneratedCodeInfo_Annotation__storage_;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = nil;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "pathArray",
+ .number = GPBGeneratedCodeInfo_Annotation_FieldNumber_PathArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated | GPBFieldPacked,
+ .dataType = GPBDataTypeInt32,
+ .offset = offsetof(GPBGeneratedCodeInfo_Annotation__storage_, pathArray),
+ .defaultValue.valueMessage = nil,
+ .dataTypeSpecific.className = NULL,
+ #if GPBOBJC_INCLUDE_FIELD_OPTIONS
+ .fieldOptions = "\000\000\000\002\020\001",
+ #else
+ .fieldOptions = NULL,
+ #endif // GPBOBJC_INCLUDE_FIELD_OPTIONS
+ },
+ {
+ .name = "sourceFile",
+ .number = GPBGeneratedCodeInfo_Annotation_FieldNumber_SourceFile,
+ .hasIndex = 1,
+ .flags = GPBFieldOptional,
+ .dataType = GPBDataTypeString,
+ .offset = offsetof(GPBGeneratedCodeInfo_Annotation__storage_, sourceFile),
+ .defaultValue.valueString = nil,
+ .dataTypeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "begin",
+ .number = GPBGeneratedCodeInfo_Annotation_FieldNumber_Begin,
+ .hasIndex = 2,
+ .flags = GPBFieldOptional,
+ .dataType = GPBDataTypeInt32,
+ .offset = offsetof(GPBGeneratedCodeInfo_Annotation__storage_, begin),
+ .defaultValue.valueInt32 = 0,
+ .dataTypeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "end",
+ .number = GPBGeneratedCodeInfo_Annotation_FieldNumber_End,
+ .hasIndex = 3,
+ .flags = GPBFieldOptional,
+ .dataType = GPBDataTypeInt32,
+ .offset = offsetof(GPBGeneratedCodeInfo_Annotation__storage_, end),
+ .defaultValue.valueInt32 = 0,
+ .dataTypeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ };
+ GPBDescriptor *localDescriptor =
+ [GPBDescriptor allocDescriptorForClass:[GPBGeneratedCodeInfo_Annotation class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBGeneratedCodeInfo_Annotation__storage_)
+ wireFormat:NO];
+ NSAssert(descriptor == nil, @"Startup recursed!");
+ descriptor = localDescriptor;
+ }
+ return descriptor;
+}
+
+@end
+
// @@protoc_insertion_point(global_scope)
diff --git a/python/google/protobuf/internal/json_format_test.py b/python/google/protobuf/internal/json_format_test.py
index be3ad11a..49e96a46 100644
--- a/python/google/protobuf/internal/json_format_test.py
+++ b/python/google/protobuf/internal/json_format_test.py
@@ -42,6 +42,12 @@ try:
import unittest2 as unittest
except ImportError:
import unittest
+from google.protobuf import any_pb2
+from google.protobuf import duration_pb2
+from google.protobuf import field_mask_pb2
+from google.protobuf import struct_pb2
+from google.protobuf import timestamp_pb2
+from google.protobuf import wrappers_pb2
from google.protobuf.internal import well_known_types
from google.protobuf import json_format
from google.protobuf.util import json_format_proto3_pb2
@@ -326,6 +332,7 @@ class JsonFormatTest(JsonFormatBase):
message.bytes_value.value = b''
message.repeated_bool_value.add().value = True
message.repeated_bool_value.add().value = False
+ message.repeated_int32_value.add()
self.assertEqual(
json.loads(json_format.MessageToJson(message, True)),
json.loads('{\n'
@@ -334,7 +341,7 @@ class JsonFormatTest(JsonFormatBase):
' "stringValue": "",'
' "bytesValue": "",'
' "repeatedBoolValue": [true, false],'
- ' "repeatedInt32Value": [],'
+ ' "repeatedInt32Value": [0],'
' "repeatedUint32Value": [],'
' "repeatedFloatValue": [],'
' "repeatedDoubleValue": [],'
@@ -346,11 +353,192 @@ class JsonFormatTest(JsonFormatBase):
parsed_message = json_format_proto3_pb2.TestWrapper()
self.CheckParseBack(message, parsed_message)
+ def testStructMessage(self):
+ message = json_format_proto3_pb2.TestStruct()
+ message.value['name'] = 'Jim'
+ message.value['age'] = 10
+ message.value['attend'] = True
+ message.value['email'] = None
+ message.value.get_or_create_struct('address')['city'] = 'SFO'
+ message.value['address']['house_number'] = 1024
+ struct_list = message.value.get_or_create_list('list')
+ struct_list.extend([6, 'seven', True, False, None])
+ struct_list.add_struct()['subkey2'] = 9
+ message.repeated_value.add()['age'] = 11
+ message.repeated_value.add()
+ self.assertEqual(
+ json.loads(json_format.MessageToJson(message, False)),
+ json.loads(
+ '{'
+ ' "value": {'
+ ' "address": {'
+ ' "city": "SFO", '
+ ' "house_number": 1024'
+ ' }, '
+ ' "age": 10, '
+ ' "name": "Jim", '
+ ' "attend": true, '
+ ' "email": null, '
+ ' "list": [6, "seven", true, false, null, {"subkey2": 9}]'
+ ' },'
+ ' "repeatedValue": [{"age": 11}, {}]'
+ '}'))
+ parsed_message = json_format_proto3_pb2.TestStruct()
+ self.CheckParseBack(message, parsed_message)
+
+ def testValueMessage(self):
+ message = json_format_proto3_pb2.TestValue()
+ message.value.string_value = 'hello'
+ message.repeated_value.add().number_value = 11.1
+ message.repeated_value.add().bool_value = False
+ message.repeated_value.add().null_value = 0
+ self.assertEqual(
+ json.loads(json_format.MessageToJson(message, False)),
+ json.loads(
+ '{'
+ ' "value": "hello",'
+ ' "repeatedValue": [11.1, false, null]'
+ '}'))
+ parsed_message = json_format_proto3_pb2.TestValue()
+ self.CheckParseBack(message, parsed_message)
+ # Can't parse back if the Value message is not set.
+ message.repeated_value.add()
+ self.assertEqual(
+ json.loads(json_format.MessageToJson(message, False)),
+ json.loads(
+ '{'
+ ' "value": "hello",'
+ ' "repeatedValue": [11.1, false, null, null]'
+ '}'))
+
+ def testListValueMessage(self):
+ message = json_format_proto3_pb2.TestListValue()
+ message.value.values.add().number_value = 11.1
+ message.value.values.add().null_value = 0
+ message.value.values.add().bool_value = True
+ message.value.values.add().string_value = 'hello'
+ message.value.values.add().struct_value['name'] = 'Jim'
+ message.repeated_value.add().values.add().number_value = 1
+ message.repeated_value.add()
+ self.assertEqual(
+ json.loads(json_format.MessageToJson(message, False)),
+ json.loads(
+ '{"value": [11.1, null, true, "hello", {"name": "Jim"}]\n,'
+ '"repeatedValue": [[1], []]}'))
+ parsed_message = json_format_proto3_pb2.TestListValue()
+ self.CheckParseBack(message, parsed_message)
+
+ def testAnyMessage(self):
+ message = json_format_proto3_pb2.TestAny()
+ value1 = json_format_proto3_pb2.MessageType()
+ value2 = json_format_proto3_pb2.MessageType()
+ value1.value = 1234
+ value2.value = 5678
+ message.value.Pack(value1)
+ message.repeated_value.add().Pack(value1)
+ message.repeated_value.add().Pack(value2)
+ message.repeated_value.add()
+ self.assertEqual(
+ json.loads(json_format.MessageToJson(message, True)),
+ json.loads(
+ '{\n'
+ ' "repeatedValue": [ {\n'
+ ' "@type": "type.googleapis.com/proto3.MessageType",\n'
+ ' "value": 1234\n'
+ ' }, {\n'
+ ' "@type": "type.googleapis.com/proto3.MessageType",\n'
+ ' "value": 5678\n'
+ ' },\n'
+ ' {}],\n'
+ ' "value": {\n'
+ ' "@type": "type.googleapis.com/proto3.MessageType",\n'
+ ' "value": 1234\n'
+ ' }\n'
+ '}\n'))
+ parsed_message = json_format_proto3_pb2.TestAny()
+ self.CheckParseBack(message, parsed_message)
+
+ def testWellKnownInAnyMessage(self):
+ message = any_pb2.Any()
+ int32_value = wrappers_pb2.Int32Value()
+ int32_value.value = 1234
+ message.Pack(int32_value)
+ self.assertEqual(
+ json.loads(json_format.MessageToJson(message, True)),
+ json.loads(
+ '{\n'
+ ' "@type": \"type.googleapis.com/google.protobuf.Int32Value\",\n'
+ ' "value": 1234\n'
+ '}\n'))
+ parsed_message = any_pb2.Any()
+ self.CheckParseBack(message, parsed_message)
+
+ timestamp = timestamp_pb2.Timestamp()
+ message.Pack(timestamp)
+ self.assertEqual(
+ json.loads(json_format.MessageToJson(message, True)),
+ json.loads(
+ '{\n'
+ ' "@type": "type.googleapis.com/google.protobuf.Timestamp",\n'
+ ' "value": "1970-01-01T00:00:00Z"\n'
+ '}\n'))
+ self.CheckParseBack(message, parsed_message)
+
+ duration = duration_pb2.Duration()
+ duration.seconds = 1
+ message.Pack(duration)
+ self.assertEqual(
+ json.loads(json_format.MessageToJson(message, True)),
+ json.loads(
+ '{\n'
+ ' "@type": "type.googleapis.com/google.protobuf.Duration",\n'
+ ' "value": "1s"\n'
+ '}\n'))
+ self.CheckParseBack(message, parsed_message)
+
+ field_mask = field_mask_pb2.FieldMask()
+ field_mask.paths.append('foo.bar')
+ field_mask.paths.append('bar')
+ message.Pack(field_mask)
+ self.assertEqual(
+ json.loads(json_format.MessageToJson(message, True)),
+ json.loads(
+ '{\n'
+ ' "@type": "type.googleapis.com/google.protobuf.FieldMask",\n'
+ ' "value": "foo.bar,bar"\n'
+ '}\n'))
+ self.CheckParseBack(message, parsed_message)
+
+ struct_message = struct_pb2.Struct()
+ struct_message['name'] = 'Jim'
+ message.Pack(struct_message)
+ self.assertEqual(
+ json.loads(json_format.MessageToJson(message, True)),
+ json.loads(
+ '{\n'
+ ' "@type": "type.googleapis.com/google.protobuf.Struct",\n'
+ ' "value": {"name": "Jim"}\n'
+ '}\n'))
+ self.CheckParseBack(message, parsed_message)
+
+ nested_any = any_pb2.Any()
+ int32_value.value = 5678
+ nested_any.Pack(int32_value)
+ message.Pack(nested_any)
+ self.assertEqual(
+ json.loads(json_format.MessageToJson(message, True)),
+ json.loads(
+ '{\n'
+ ' "@type": "type.googleapis.com/google.protobuf.Any",\n'
+ ' "value": {\n'
+ ' "@type": "type.googleapis.com/google.protobuf.Int32Value",\n'
+ ' "value": 5678\n'
+ ' }\n'
+ '}\n'))
+ self.CheckParseBack(message, parsed_message)
+
def testParseNull(self):
message = json_format_proto3_pb2.TestMessage()
- message.repeated_int32_value.append(1)
- message.repeated_int32_value.append(2)
- message.repeated_int32_value.append(3)
parsed_message = json_format_proto3_pb2.TestMessage()
self.FillAllFields(parsed_message)
json_format.Parse('{"int32Value": null, '
@@ -364,7 +552,7 @@ class JsonFormatTest(JsonFormatBase):
'"bytesValue": null,'
'"messageValue": null,'
'"enumValue": null,'
- '"repeatedInt32Value": [1, 2, null, 3],'
+ '"repeatedInt32Value": null,'
'"repeatedInt64Value": null,'
'"repeatedUint32Value": null,'
'"repeatedUint64Value": null,'
@@ -378,6 +566,13 @@ class JsonFormatTest(JsonFormatBase):
'}',
parsed_message)
self.assertEqual(message, parsed_message)
+ self.assertRaisesRegexp(
+ json_format.ParseError,
+ 'Failed to parse repeatedInt32Value field: '
+ 'null is not allowed to be used as an element in a repeated field.',
+ json_format.Parse,
+ '{"repeatedInt32Value":[1, null]}',
+ parsed_message)
def testNanFloat(self):
message = json_format_proto3_pb2.TestMessage()
@@ -529,6 +724,45 @@ class JsonFormatTest(JsonFormatBase):
' should not have multiple "oneof_value" oneof fields.',
json_format.Parse, text, message)
+ def testInvalidListValue(self):
+ message = json_format_proto3_pb2.TestListValue()
+ text = '{"value": 1234}'
+ self.assertRaisesRegexp(
+ json_format.ParseError,
+ r'Failed to parse value field: ListValue must be in \[\] which is 1234',
+ json_format.Parse, text, message)
+
+ def testInvalidStruct(self):
+ message = json_format_proto3_pb2.TestStruct()
+ text = '{"value": 1234}'
+ self.assertRaisesRegexp(
+ json_format.ParseError,
+ 'Failed to parse value field: Struct must be in a dict which is 1234',
+ json_format.Parse, text, message)
+
+ def testInvalidAny(self):
+ message = any_pb2.Any()
+ text = '{"@type": "type.googleapis.com/google.protobuf.Int32Value"}'
+ self.assertRaisesRegexp(
+ KeyError,
+ 'value',
+ json_format.Parse, text, message)
+ text = '{"value": 1234}'
+ self.assertRaisesRegexp(
+ json_format.ParseError,
+ '@type is missing when parsing any message.',
+ json_format.Parse, text, message)
+ text = '{"@type": "type.googleapis.com/MessageNotExist", "value": 1234}'
+ self.assertRaisesRegexp(
+ TypeError,
+ 'Can not find message descriptor by type_url: '
+ 'type.googleapis.com/MessageNotExist.',
+ json_format.Parse, text, message)
+ # Only last part is to be used.
+ text = (r'{"@type": "incorrect.googleapis.com/google.protobuf.Int32Value",'
+ r'"value": 1234}')
+ json_format.Parse(text, message)
+
if __name__ == '__main__':
unittest.main()
diff --git a/python/google/protobuf/internal/well_known_types.py b/python/google/protobuf/internal/well_known_types.py
index d3de9831..d35fcc5f 100644
--- a/python/google/protobuf/internal/well_known_types.py
+++ b/python/google/protobuf/internal/well_known_types.py
@@ -34,6 +34,7 @@ This files defines well known classes which need extra maintenance including:
- Any
- Duration
- FieldMask
+ - Struct
- Timestamp
"""
@@ -41,6 +42,7 @@ __author__ = 'jieluo@google.com (Jie Luo)'
from datetime import datetime
from datetime import timedelta
+import six
from google.protobuf.descriptor import FieldDescriptor
@@ -64,9 +66,12 @@ class ParseError(Error):
class Any(object):
"""Class for Any Message type."""
- def Pack(self, msg):
+ def Pack(self, msg, type_url_prefix='type.googleapis.com/'):
"""Packs the specified message into current Any message."""
- self.type_url = 'type.googleapis.com/%s' % msg.DESCRIPTOR.full_name
+ if len(type_url_prefix) < 1 or type_url_prefix[-1] != '/':
+ self.type_url = '%s/%s' % (type_url_prefix, msg.DESCRIPTOR.full_name)
+ else:
+ self.type_url = '%s%s' % (type_url_prefix, msg.DESCRIPTOR.full_name)
self.value = msg.SerializeToString()
def Unpack(self, msg):
@@ -614,9 +619,102 @@ def _AddFieldPaths(node, prefix, field_mask):
_AddFieldPaths(node[name], child_path, field_mask)
+_INT_OR_FLOAT = six.integer_types + (float,)
+
+
+def _SetStructValue(struct_value, value):
+ if value is None:
+ struct_value.null_value = 0
+ elif isinstance(value, bool):
+ # Note: this check must come before the number check because in Python
+ # True and False are also considered numbers.
+ struct_value.bool_value = value
+ elif isinstance(value, six.string_types):
+ struct_value.string_value = value
+ elif isinstance(value, _INT_OR_FLOAT):
+ struct_value.number_value = value
+ else:
+ raise ValueError('Unexpected type')
+
+
+def _GetStructValue(struct_value):
+ which = struct_value.WhichOneof('kind')
+ if which == 'struct_value':
+ return struct_value.struct_value
+ elif which == 'null_value':
+ return None
+ elif which == 'number_value':
+ return struct_value.number_value
+ elif which == 'string_value':
+ return struct_value.string_value
+ elif which == 'bool_value':
+ return struct_value.bool_value
+ elif which == 'list_value':
+ return struct_value.list_value
+ elif which is None:
+ raise ValueError('Value not set')
+
+
+class Struct(object):
+ """Class for Struct message type."""
+
+ __slots__ = []
+
+ def __getitem__(self, key):
+ return _GetStructValue(self.fields[key])
+
+ def __setitem__(self, key, value):
+ _SetStructValue(self.fields[key], value)
+
+ def get_or_create_list(self, key):
+ """Returns a list for this key, creating if it didn't exist already."""
+ return self.fields[key].list_value
+
+ def get_or_create_struct(self, key):
+ """Returns a struct for this key, creating if it didn't exist already."""
+ return self.fields[key].struct_value
+
+ # TODO(haberman): allow constructing/merging from dict.
+
+
+class ListValue(object):
+ """Class for ListValue message type."""
+
+ def __len__(self):
+ return len(self.values)
+
+ def append(self, value):
+ _SetStructValue(self.values.add(), value)
+
+ def extend(self, elem_seq):
+ for value in elem_seq:
+ self.append(value)
+
+ def __getitem__(self, index):
+ """Retrieves item by the specified index."""
+ return _GetStructValue(self.values.__getitem__(index))
+
+ def __setitem__(self, index, value):
+ _SetStructValue(self.values.__getitem__(index), value)
+
+ def items(self):
+ for i in range(len(self)):
+ yield self[i]
+
+ def add_struct(self):
+ """Appends and returns a struct value as the next value in the list."""
+ return self.values.add().struct_value
+
+ def add_list(self):
+ """Appends and returns a list value as the next value in the list."""
+ return self.values.add().list_value
+
+
WKTBASES = {
'google.protobuf.Any': Any,
'google.protobuf.Duration': Duration,
'google.protobuf.FieldMask': FieldMask,
+ 'google.protobuf.ListValue': ListValue,
+ 'google.protobuf.Struct': Struct,
'google.protobuf.Timestamp': Timestamp,
}
diff --git a/python/google/protobuf/internal/well_known_types_test.py b/python/google/protobuf/internal/well_known_types_test.py
index 0e31e6f8..6acbee22 100644
--- a/python/google/protobuf/internal/well_known_types_test.py
+++ b/python/google/protobuf/internal/well_known_types_test.py
@@ -41,13 +41,17 @@ try:
except ImportError:
import unittest
+from google.protobuf import any_pb2
from google.protobuf import duration_pb2
from google.protobuf import field_mask_pb2
+from google.protobuf import struct_pb2
from google.protobuf import timestamp_pb2
from google.protobuf import unittest_pb2
+from google.protobuf.internal import any_test_pb2
from google.protobuf.internal import test_util
from google.protobuf.internal import well_known_types
from google.protobuf import descriptor
+from google.protobuf import text_format
class TimeUtilTestBase(unittest.TestCase):
@@ -509,5 +513,124 @@ class FieldMaskTest(unittest.TestCase):
self.assertEqual(1, len(nested_dst.payload.repeated_int32))
self.assertEqual(1234, nested_dst.payload.repeated_int32[0])
+
+class StructTest(unittest.TestCase):
+
+ def testStruct(self):
+ struct = struct_pb2.Struct()
+ struct_class = struct.__class__
+
+ struct['key1'] = 5
+ struct['key2'] = 'abc'
+ struct['key3'] = True
+ struct.get_or_create_struct('key4')['subkey'] = 11.0
+ struct_list = struct.get_or_create_list('key5')
+ struct_list.extend([6, 'seven', True, False, None])
+ struct_list.add_struct()['subkey2'] = 9
+
+ self.assertTrue(isinstance(struct, well_known_types.Struct))
+ self.assertEquals(5, struct['key1'])
+ self.assertEquals('abc', struct['key2'])
+ self.assertIs(True, struct['key3'])
+ self.assertEquals(11, struct['key4']['subkey'])
+ inner_struct = struct_class()
+ inner_struct['subkey2'] = 9
+ self.assertEquals([6, 'seven', True, False, None, inner_struct],
+ list(struct['key5'].items()))
+
+ serialized = struct.SerializeToString()
+
+ struct2 = struct_pb2.Struct()
+ struct2.ParseFromString(serialized)
+
+ self.assertEquals(struct, struct2)
+
+ self.assertTrue(isinstance(struct2, well_known_types.Struct))
+ self.assertEquals(5, struct2['key1'])
+ self.assertEquals('abc', struct2['key2'])
+ self.assertIs(True, struct2['key3'])
+ self.assertEquals(11, struct2['key4']['subkey'])
+ self.assertEquals([6, 'seven', True, False, None, inner_struct],
+ list(struct2['key5'].items()))
+
+ struct_list = struct2['key5']
+ self.assertEquals(6, struct_list[0])
+ self.assertEquals('seven', struct_list[1])
+ self.assertEquals(True, struct_list[2])
+ self.assertEquals(False, struct_list[3])
+ self.assertEquals(None, struct_list[4])
+ self.assertEquals(inner_struct, struct_list[5])
+
+ struct_list[1] = 7
+ self.assertEquals(7, struct_list[1])
+
+ struct_list.add_list().extend([1, 'two', True, False, None])
+ self.assertEquals([1, 'two', True, False, None],
+ list(struct_list[6].items()))
+
+ text_serialized = str(struct)
+ struct3 = struct_pb2.Struct()
+ text_format.Merge(text_serialized, struct3)
+ self.assertEquals(struct, struct3)
+
+ struct.get_or_create_struct('key3')['replace'] = 12
+ self.assertEquals(12, struct['key3']['replace'])
+
+
+class AnyTest(unittest.TestCase):
+
+ def testAnyMessage(self):
+ # Creates and sets message.
+ msg = any_test_pb2.TestAny()
+ msg_descriptor = msg.DESCRIPTOR
+ all_types = unittest_pb2.TestAllTypes()
+ all_descriptor = all_types.DESCRIPTOR
+ all_types.repeated_string.append(u'\u00fc\ua71f')
+ # Packs to Any.
+ msg.value.Pack(all_types)
+ self.assertEqual(msg.value.type_url,
+ 'type.googleapis.com/%s' % all_descriptor.full_name)
+ self.assertEqual(msg.value.value,
+ all_types.SerializeToString())
+ # Tests Is() method.
+ self.assertTrue(msg.value.Is(all_descriptor))
+ self.assertFalse(msg.value.Is(msg_descriptor))
+ # Unpacks Any.
+ unpacked_message = unittest_pb2.TestAllTypes()
+ self.assertTrue(msg.value.Unpack(unpacked_message))
+ self.assertEqual(all_types, unpacked_message)
+ # Unpacks to different type.
+ self.assertFalse(msg.value.Unpack(msg))
+ # Only Any messages have Pack method.
+ try:
+ msg.Pack(all_types)
+ except AttributeError:
+ pass
+ else:
+ raise AttributeError('%s should not have Pack method.' %
+ msg_descriptor.full_name)
+
+ def testPackWithCustomTypeUrl(self):
+ submessage = any_test_pb2.TestAny()
+ submessage.int_value = 12345
+ msg = any_pb2.Any()
+ # Pack with a custom type URL prefix.
+ msg.Pack(submessage, 'type.myservice.com')
+ self.assertEqual(msg.type_url,
+ 'type.myservice.com/%s' % submessage.DESCRIPTOR.full_name)
+ # Pack with a custom type URL prefix ending with '/'.
+ msg.Pack(submessage, 'type.myservice.com/')
+ self.assertEqual(msg.type_url,
+ 'type.myservice.com/%s' % submessage.DESCRIPTOR.full_name)
+ # Pack with an empty type URL prefix.
+ msg.Pack(submessage, '')
+ self.assertEqual(msg.type_url,
+ '/%s' % submessage.DESCRIPTOR.full_name)
+ # Test unpacking the type.
+ unpacked_message = any_test_pb2.TestAny()
+ self.assertTrue(msg.Unpack(unpacked_message))
+ self.assertEqual(submessage, unpacked_message)
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/python/google/protobuf/json_format.py b/python/google/protobuf/json_format.py
index cb76e116..23382bdb 100644
--- a/python/google/protobuf/json_format.py
+++ b/python/google/protobuf/json_format.py
@@ -45,10 +45,11 @@ __author__ = 'jieluo@google.com (Jie Luo)'
import base64
import json
import math
-from six import text_type
+import six
import sys
from google.protobuf import descriptor
+from google.protobuf import symbol_database
_TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S'
_INT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT32,
@@ -96,11 +97,15 @@ def MessageToJson(message, including_default_value_fields=False):
def _MessageToJsonObject(message, including_default_value_fields):
"""Converts message to an object according to Proto3 JSON Specification."""
message_descriptor = message.DESCRIPTOR
- if hasattr(message, 'ToJsonString'):
- return message.ToJsonString()
+ full_name = message_descriptor.full_name
if _IsWrapperMessage(message_descriptor):
return _WrapperMessageToJsonObject(message)
- return _RegularMessageToJsonObject(message, including_default_value_fields)
+ if full_name in _WKTJSONMETHODS:
+ return _WKTJSONMETHODS[full_name][0](
+ message, including_default_value_fields)
+ js = {}
+ return _RegularMessageToJsonObject(
+ message, js, including_default_value_fields)
def _IsMapEntry(field):
@@ -109,9 +114,8 @@ def _IsMapEntry(field):
field.message_type.GetOptions().map_entry)
-def _RegularMessageToJsonObject(message, including_default_value_fields):
+def _RegularMessageToJsonObject(message, js, including_default_value_fields):
"""Converts normal message according to Proto3 JSON Specification."""
- js = {}
fields = message.ListFields()
include_default = including_default_value_fields
@@ -200,6 +204,79 @@ def _FieldToJsonObject(
return value
+def _AnyMessageToJsonObject(message, including_default):
+ """Converts Any message according to Proto3 JSON Specification."""
+ if not message.ListFields():
+ return {}
+ js = {}
+ type_url = message.type_url
+ js['@type'] = type_url
+ sub_message = _CreateMessageFromTypeUrl(type_url)
+ sub_message.ParseFromString(message.value)
+ message_descriptor = sub_message.DESCRIPTOR
+ full_name = message_descriptor.full_name
+ if _IsWrapperMessage(message_descriptor):
+ js['value'] = _WrapperMessageToJsonObject(sub_message)
+ return js
+ if full_name in _WKTJSONMETHODS:
+ js['value'] = _WKTJSONMETHODS[full_name][0](sub_message, including_default)
+ return js
+ return _RegularMessageToJsonObject(sub_message, js, including_default)
+
+
+def _CreateMessageFromTypeUrl(type_url):
+ # TODO(jieluo): Should add a way that users can register the type resolver
+ # instead of the default one.
+ db = symbol_database.Default()
+ type_name = type_url.split('/')[-1]
+ try:
+ message_descriptor = db.pool.FindMessageTypeByName(type_name)
+ except KeyError:
+ raise TypeError(
+ 'Can not find message descriptor by type_url: {0}.'.format(type_url))
+ message_class = db.GetPrototype(message_descriptor)
+ return message_class()
+
+
+def _GenericMessageToJsonObject(message, unused_including_default):
+ """Converts message by ToJsonString according to Proto3 JSON Specification."""
+ # Duration, Timestamp and FieldMask have ToJsonString method to do the
+ # convert. Users can also call the method directly.
+ return message.ToJsonString()
+
+
+def _ValueMessageToJsonObject(message, unused_including_default=False):
+ """Converts Value message according to Proto3 JSON Specification."""
+ which = message.WhichOneof('kind')
+ # If the Value message is not set treat as null_value when serialize
+ # to JSON. The parse back result will be different from original message.
+ if which is None or which == 'null_value':
+ return None
+ if which == 'list_value':
+ return _ListValueMessageToJsonObject(message.list_value)
+ if which == 'struct_value':
+ value = message.struct_value
+ else:
+ value = getattr(message, which)
+ oneof_descriptor = message.DESCRIPTOR.fields_by_name[which]
+ return _FieldToJsonObject(oneof_descriptor, value)
+
+
+def _ListValueMessageToJsonObject(message, unused_including_default=False):
+ """Converts ListValue message according to Proto3 JSON Specification."""
+ return [_ValueMessageToJsonObject(value)
+ for value in message.values]
+
+
+def _StructMessageToJsonObject(message, unused_including_default=False):
+ """Converts Struct message according to Proto3 JSON Specification."""
+ fields = message.fields
+ js = {}
+ for key in fields.keys():
+ js[key] = _ValueMessageToJsonObject(fields[key])
+ return js
+
+
def _IsWrapperMessage(message_descriptor):
return message_descriptor.file.name == 'google/protobuf/wrappers.proto'
@@ -231,7 +308,7 @@ def Parse(text, message):
Raises::
ParseError: On JSON parsing problems.
"""
- if not isinstance(text, text_type): text = text.decode('utf-8')
+ if not isinstance(text, six.text_type): text = text.decode('utf-8')
try:
if sys.version_info < (2, 7):
# object_pair_hook is not supported before python2.7
@@ -240,7 +317,7 @@ def Parse(text, message):
js = json.loads(text, object_pairs_hook=_DuplicateChecker)
except ValueError as e:
raise ParseError('Failed to load JSON: {0}.'.format(str(e)))
- _ConvertFieldValuePair(js, message)
+ _ConvertMessage(js, message)
return message
@@ -291,13 +368,22 @@ def _ConvertFieldValuePair(js, message):
if not isinstance(value, list):
raise ParseError('repeated field {0} must be in [] which is '
'{1}.'.format(name, value))
- for item in value:
- if item is None:
- continue
- if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+ if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+ # Repeated message field.
+ for item in value:
sub_message = getattr(message, field.name).add()
+ # None is a null_value in Value.
+ if (item is None and
+ sub_message.DESCRIPTOR.full_name != 'google.protobuf.Value'):
+ raise ParseError('null is not allowed to be used as an element'
+ ' in a repeated field.')
_ConvertMessage(item, sub_message)
- else:
+ else:
+ # Repeated scalar field.
+ for item in value:
+ if item is None:
+ raise ParseError('null is not allowed to be used as an element'
+ ' in a repeated field.')
getattr(message, field.name).append(
_ConvertScalarFieldValue(item, field))
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
@@ -327,13 +413,87 @@ def _ConvertMessage(value, message):
ParseError: In case of convert problems.
"""
message_descriptor = message.DESCRIPTOR
- if hasattr(message, 'FromJsonString'):
- message.FromJsonString(value)
- elif _IsWrapperMessage(message_descriptor):
+ full_name = message_descriptor.full_name
+ if _IsWrapperMessage(message_descriptor):
_ConvertWrapperMessage(value, message)
+ elif full_name in _WKTJSONMETHODS:
+ _WKTJSONMETHODS[full_name][1](value, message)
else:
_ConvertFieldValuePair(value, message)
+
+def _ConvertAnyMessage(value, message):
+ """Convert a JSON representation into Any message."""
+ if isinstance(value, dict) and not value:
+ return
+ try:
+ type_url = value['@type']
+ except KeyError:
+ raise ParseError('@type is missing when parsing any message.')
+
+ sub_message = _CreateMessageFromTypeUrl(type_url)
+ message_descriptor = sub_message.DESCRIPTOR
+ full_name = message_descriptor.full_name
+ if _IsWrapperMessage(message_descriptor):
+ _ConvertWrapperMessage(value['value'], sub_message)
+ elif full_name in _WKTJSONMETHODS:
+ _WKTJSONMETHODS[full_name][1](value['value'], sub_message)
+ else:
+ del value['@type']
+ _ConvertFieldValuePair(value, sub_message)
+ # Sets Any message
+ message.value = sub_message.SerializeToString()
+ message.type_url = type_url
+
+
+def _ConvertGenericMessage(value, message):
+ """Convert a JSON representation into message with FromJsonString."""
+ # Durantion, Timestamp, FieldMask have FromJsonString method to do the
+ # convert. Users can also call the method directly.
+ message.FromJsonString(value)
+
+
+_INT_OR_FLOAT = six.integer_types + (float,)
+
+
+def _ConvertValueMessage(value, message):
+ """Convert a JSON representation into Value message."""
+ if isinstance(value, dict):
+ _ConvertStructMessage(value, message.struct_value)
+ elif isinstance(value, list):
+ _ConvertListValueMessage(value, message.list_value)
+ elif value is None:
+ message.null_value = 0
+ elif isinstance(value, bool):
+ message.bool_value = value
+ elif isinstance(value, six.string_types):
+ message.string_value = value
+ elif isinstance(value, _INT_OR_FLOAT):
+ message.number_value = value
+ else:
+ raise ParseError('Unexpected type for Value message.')
+
+
+def _ConvertListValueMessage(value, message):
+ """Convert a JSON representation into ListValue message."""
+ if not isinstance(value, list):
+ raise ParseError(
+ 'ListValue must be in [] which is {0}.'.format(value))
+ message.ClearField('values')
+ for item in value:
+ _ConvertValueMessage(item, message.values.add())
+
+
+def _ConvertStructMessage(value, message):
+ """Convert a JSON representation into Struct message."""
+ if not isinstance(value, dict):
+ raise ParseError(
+ 'Struct must be in a dict which is {0}.'.format(value))
+ for key in value:
+ _ConvertValueMessage(value[key], message.fields[key])
+ return
+
+
def _ConvertWrapperMessage(value, message):
"""Convert a JSON representation into Wrapper message."""
field = message.DESCRIPTOR.fields_by_name['value']
@@ -353,7 +513,8 @@ def _ConvertMapFieldValue(value, message, field):
"""
if not isinstance(value, dict):
raise ParseError(
- 'Map fieled {0} must be in {} which is {1}.'.format(field.name, value))
+ 'Map field {0} must be in a dict which is {1}.'.format(
+ field.name, value))
key_field = field.message_type.fields_by_name['key']
value_field = field.message_type.fields_by_name['value']
for key in value:
@@ -416,7 +577,7 @@ def _ConvertInteger(value):
if isinstance(value, float):
raise ParseError('Couldn\'t parse integer: {0}.'.format(value))
- if isinstance(value, text_type) and value.find(' ') != -1:
+ if isinstance(value, six.text_type) and value.find(' ') != -1:
raise ParseError('Couldn\'t parse integer: "{0}".'.format(value))
return int(value)
@@ -465,3 +626,20 @@ def _ConvertBool(value, require_str):
if not isinstance(value, bool):
raise ParseError('Expected true or false without quotes.')
return value
+
+_WKTJSONMETHODS = {
+ 'google.protobuf.Any': [_AnyMessageToJsonObject,
+ _ConvertAnyMessage],
+ 'google.protobuf.Duration': [_GenericMessageToJsonObject,
+ _ConvertGenericMessage],
+ 'google.protobuf.FieldMask': [_GenericMessageToJsonObject,
+ _ConvertGenericMessage],
+ 'google.protobuf.ListValue': [_ListValueMessageToJsonObject,
+ _ConvertListValueMessage],
+ 'google.protobuf.Struct': [_StructMessageToJsonObject,
+ _ConvertStructMessage],
+ 'google.protobuf.Timestamp': [_GenericMessageToJsonObject,
+ _ConvertGenericMessage],
+ 'google.protobuf.Value': [_ValueMessageToJsonObject,
+ _ConvertValueMessage]
+}
diff --git a/python/google/protobuf/pyext/map_container.cc b/python/google/protobuf/pyext/map_container.cc
index 516662ee..df9138a4 100644
--- a/python/google/protobuf/pyext/map_container.cc
+++ b/python/google/protobuf/pyext/map_container.cc
@@ -797,7 +797,7 @@ static PyMethodDef MessageMapMethods[] = {
PyType_Spec MessageMapContainer_Type_spec = {
FULL_MODULE_NAME ".MessageMapContainer",
- sizeof(MapContainer),
+ sizeof(MessageMapContainer),
0,
Py_TPFLAGS_DEFAULT,
MessageMapContainer_Type_slots
diff --git a/src/Makefile.am b/src/Makefile.am
index 462eb3e1..073673a5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -342,6 +342,8 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/java/java_enum_lite.h \
google/protobuf/compiler/java/java_extension.cc \
google/protobuf/compiler/java/java_extension.h \
+ google/protobuf/compiler/java/java_extension_lite.cc \
+ google/protobuf/compiler/java/java_extension_lite.h \
google/protobuf/compiler/java/java_field.cc \
google/protobuf/compiler/java/java_field.h \
google/protobuf/compiler/java/java_file.cc \
@@ -727,6 +729,7 @@ protobuf_test_SOURCES = \
google/protobuf/compiler/cpp/cpp_unittest.h \
google/protobuf/compiler/cpp/cpp_unittest.cc \
google/protobuf/compiler/cpp/cpp_plugin_unittest.cc \
+ google/protobuf/compiler/cpp/metadata_test.cc \
google/protobuf/compiler/java/java_plugin_unittest.cc \
google/protobuf/compiler/java/java_doc_comment_unittest.cc \
google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc \
diff --git a/src/README.md b/src/README.md
new file mode 100644
index 00000000..4e312c0c
--- /dev/null
+++ b/src/README.md
@@ -0,0 +1,209 @@
+Protocol Buffers - Google's data interchange format
+===================================================
+
+[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf)
+
+Copyright 2008 Google Inc.
+
+https://developers.google.com/protocol-buffers/
+
+C++ Installation - Unix
+-----------------------
+
+To build protobuf from source, the following tools are needed:
+
+ * autoconf
+ * automake
+ * libtool
+ * curl (used to download gmock)
+
+On Ubuntu, you can install them with:
+
+ $ sudo apt-get install autoconf automake libtool curl
+
+On other platforms, please use the corresponding package managing tool to
+install them before proceeding.
+
+If you get the source from github, you need to generate the configure script
+first:
+
+ $ ./autogen.sh
+
+This will download gmock source (which is used for C++ Protocol Buffer
+unit-tests) to the current directory and run automake, autoconf, etc.
+to generate the configure script and various template makefiles.
+
+You can skip this step if you are using a release package (which already
+contains gmock and the configure script).
+
+To build and install the C++ Protocol Buffer runtime and the Protocol
+Buffer compiler (protoc) execute the following:
+
+ $ ./configure
+ $ make
+ $ make check
+ $ sudo make install
+ $ sudo ldconfig # refresh shared library cache.
+
+If "make check" fails, you can still install, but it is likely that
+some features of this library will not work correctly on your system.
+Proceed at your own risk.
+
+For advanced usage information on configure and make, please refer to the
+autoconf documentation:
+
+ http://www.gnu.org/software/autoconf/manual/autoconf.html#Running-configure-Scripts
+
+**Hint on install location**
+
+ By default, the package will be installed to /usr/local. However,
+ on many platforms, /usr/local/lib is not part of LD_LIBRARY_PATH.
+ You can add it, but it may be easier to just install to /usr
+ instead. To do this, invoke configure as follows:
+
+ ./configure --prefix=/usr
+
+ If you already built the package with a different prefix, make sure
+ to run "make clean" before building again.
+
+**Compiling dependent packages**
+
+ To compile a package that uses Protocol Buffers, you need to pass
+ various flags to your compiler and linker. As of version 2.2.0,
+ Protocol Buffers integrates with pkg-config to manage this. If you
+ have pkg-config installed, then you can invoke it to get a list of
+ flags like so:
+
+ pkg-config --cflags protobuf # print compiler flags
+ pkg-config --libs protobuf # print linker flags
+ pkg-config --cflags --libs protobuf # print both
+
+ For example:
+
+ c++ my_program.cc my_proto.pb.cc `pkg-config --cflags --libs protobuf`
+
+ Note that packages written prior to the 2.2.0 release of Protocol
+ Buffers may not yet integrate with pkg-config to get flags, and may
+ not pass the correct set of flags to correctly link against
+ libprotobuf. If the package in question uses autoconf, you can
+ often fix the problem by invoking its configure script like:
+
+ configure CXXFLAGS="$(pkg-config --cflags protobuf)" \
+ LIBS="$(pkg-config --libs protobuf)"
+
+ This will force it to use the correct flags.
+
+ If you are writing an autoconf-based package that uses Protocol
+ Buffers, you should probably use the PKG_CHECK_MODULES macro in your
+ configure script like:
+
+ PKG_CHECK_MODULES([protobuf], [protobuf])
+
+ See the pkg-config man page for more info.
+
+ If you only want protobuf-lite, substitute "protobuf-lite" in place
+ of "protobuf" in these examples.
+
+**Note for Mac users**
+
+ For a Mac system, Unix tools are not available by default. You will first need
+ to install Xcode from the Mac AppStore and then run the following command from
+ a terminal:
+
+ $ sudo xcode-select --install
+
+ To install Unix tools, you can install "port" following the instructions at
+ https://www.macports.org . This will reside in /opt/local/bin/port for most
+ Mac installations.
+
+ $ sudo /opt/local/bin/port install autoconf automake libtool
+
+ Then follow the Unix instructions above.
+
+**Note for cross-compiling**
+
+ The makefiles normally invoke the protoc executable that they just
+ built in order to build tests. When cross-compiling, the protoc
+ executable may not be executable on the host machine. In this case,
+ you must build a copy of protoc for the host machine first, then use
+ the --with-protoc option to tell configure to use it instead. For
+ example:
+
+ ./configure --with-protoc=protoc
+
+ This will use the installed protoc (found in your $PATH) instead of
+ trying to execute the one built during the build process. You can
+ also use an executable that hasn't been installed. For example, if
+ you built the protobuf package for your host machine in ../host,
+ you might do:
+
+ ./configure --with-protoc=../host/src/protoc
+
+ Either way, you must make sure that the protoc executable you use
+ has the same version as the protobuf source code you are trying to
+ use it with.
+
+**Note for Solaris users**
+
+ Solaris 10 x86 has a bug that will make linking fail, complaining
+ about libstdc++.la being invalid. We have included a work-around
+ in this package. To use the work-around, run configure as follows:
+
+ ./configure LDFLAGS=-L$PWD/src/solaris
+
+ See src/solaris/libstdc++.la for more info on this bug.
+
+**Note for HP C++ Tru64 users**
+
+ To compile invoke configure as follows:
+
+ ./configure CXXFLAGS="-O -std ansi -ieee -D__USE_STD_IOSTREAM"
+
+ Also, you will need to use gmake instead of make.
+
+**Note for AIX users**
+
+ Compile using the IBM xlC C++ compiler as follows:
+
+ ./configure CXX=xlC
+
+ Also, you will need to use GNU `make` (`gmake`) instead of AIX `make`.
+
+C++ Installation - Windows
+--------------------------
+
+If you only need the protoc binary, you can download it from the release
+page:
+
+ https://github.com/google/protobuf/releases
+
+In the downloads section, download the zip file protoc-$VERSION-win32.zip.
+It contains the protoc binary as well as public proto files of protobuf
+library.
+
+To build from source using Microsoft Visual C++, see cmake/README.md.
+
+To build from source using Cygwin or MinGW, follow the Unix installation
+instructions, above.
+
+Binary Compatibility Warning
+----------------------------
+
+Due to the nature of C++, it is unlikely that any two versions of the
+Protocol Buffers C++ runtime libraries will have compatible ABIs.
+That is, if you linked an executable against an older version of
+libprotobuf, it is unlikely to work with a newer version without
+re-compiling. This problem, when it occurs, will normally be detected
+immediately on startup of your app. Still, you may want to consider
+using static linkage. You can configure this package to install
+static libraries only using:
+
+ ./configure --disable-shared
+
+Usage
+-----
+
+The complete documentation for Protocol Buffers is available via the
+web at:
+
+ https://developers.google.com/protocol-buffers/
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index deb3d0f1..3a816b05 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -33,6 +33,7 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/stubs/platform_macros.h>
#include <stdio.h>
#include <sys/types.h>
@@ -48,6 +49,10 @@
#include <iostream>
#include <ctype.h>
+#ifdef GOOGLE_PROTOBUF_ARCH_SPARC
+#include <limits.h> //For PATH_MAX
+#endif
+
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
diff --git a/src/google/protobuf/compiler/cpp/metadata_test.cc b/src/google/protobuf/compiler/cpp/metadata_test.cc
new file mode 100644
index 00000000..422eb73b
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/metadata_test.cc
@@ -0,0 +1,58 @@
+// 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.
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/cpp_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/file.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+namespace {
+
+} // namespace
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_extension_lite.cc b/src/google/protobuf/compiler/java/java_extension_lite.cc
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_extension_lite.cc
diff --git a/src/google/protobuf/compiler/java/java_extension_lite.h b/src/google/protobuf/compiler/java/java_extension_lite.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_extension_lite.h
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 5715a432..22a70c32 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -664,34 +664,34 @@ GenerateParseFromMethods(io::Printer* printer) {
"}\n"
"public static $classname$ parseFrom(java.io.InputStream input)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseFrom(input);\n"
+ " return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input);"
"}\n"
"public static $classname$ parseFrom(\n"
" java.io.InputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseFrom(input, extensionRegistry);\n"
+ " return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry);"
"}\n"
"public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseDelimitedFrom(input);\n"
+ " return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input);"
"}\n"
"public static $classname$ parseDelimitedFrom(\n"
" java.io.InputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseDelimitedFrom(input, extensionRegistry);\n"
+ " return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input, extensionRegistry);"
"}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.CodedInputStream input)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseFrom(input);\n"
+ " return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input);"
"}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.CodedInputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseFrom(input, extensionRegistry);\n"
+ " return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry);"
"}\n"
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
@@ -1217,9 +1217,8 @@ GenerateParsingConstructor(io::Printer* printer) {
"} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
" throw new RuntimeException(e.setUnfinishedMessage(this));\n"
"} catch (java.io.IOException e) {\n"
- " throw new RuntimeException(\n"
- " new com.google.protobuf.InvalidProtocolBufferException(\n"
- " e.getMessage()).setUnfinishedMessage(this));\n"
+ " throw new RuntimeException(new com.google.protobuf.InvalidProtocolBufferException(e)\n"
+ " .setUnfinishedMessage(this));\n"
"} finally {\n");
printer->Indent();
diff --git a/src/google/protobuf/compiler/java/java_message_builder.cc b/src/google/protobuf/compiler/java/java_message_builder.cc
index 72694119..5d535034 100644
--- a/src/google/protobuf/compiler/java/java_message_builder.cc
+++ b/src/google/protobuf/compiler/java/java_message_builder.cc
@@ -538,7 +538,7 @@ GenerateBuilderParsingMethods(io::Printer* printer) {
" parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n"
" } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
" parsedMessage = ($classname$) e.getUnfinishedMessage();\n"
- " throw e;\n"
+ " throw e.unwrapIOException();\n"
" } finally {\n"
" if (parsedMessage != null) {\n"
" mergeFrom(parsedMessage);\n"
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index eda6280f..ff0cfcf8 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -93,6 +93,12 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
const ::google::protobuf::Descriptor* SourceCodeInfo_Location_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
SourceCodeInfo_Location_reflection_ = NULL;
+const ::google::protobuf::Descriptor* GeneratedCodeInfo_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ GeneratedCodeInfo_reflection_ = NULL;
+const ::google::protobuf::Descriptor* GeneratedCodeInfo_Annotation_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ GeneratedCodeInfo_Annotation_reflection_ = NULL;
} // namespace
@@ -521,6 +527,39 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
sizeof(SourceCodeInfo_Location),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _internal_metadata_),
-1);
+ GeneratedCodeInfo_descriptor_ = file->message_type(18);
+ static const int GeneratedCodeInfo_offsets_[1] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo, annotation_),
+ };
+ GeneratedCodeInfo_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ GeneratedCodeInfo_descriptor_,
+ GeneratedCodeInfo::default_instance_,
+ GeneratedCodeInfo_offsets_,
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo, _has_bits_[0]),
+ -1,
+ -1,
+ sizeof(GeneratedCodeInfo),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo, _internal_metadata_),
+ -1);
+ GeneratedCodeInfo_Annotation_descriptor_ = GeneratedCodeInfo_descriptor_->nested_type(0);
+ static const int GeneratedCodeInfo_Annotation_offsets_[4] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, path_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, source_file_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, begin_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, end_),
+ };
+ GeneratedCodeInfo_Annotation_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ GeneratedCodeInfo_Annotation_descriptor_,
+ GeneratedCodeInfo_Annotation::default_instance_,
+ GeneratedCodeInfo_Annotation_offsets_,
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _has_bits_[0]),
+ -1,
+ -1,
+ sizeof(GeneratedCodeInfo_Annotation),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _internal_metadata_),
+ -1);
}
namespace {
@@ -577,6 +616,10 @@ void protobuf_RegisterTypes(const ::std::string&) {
SourceCodeInfo_descriptor_, &SourceCodeInfo::default_instance());
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
SourceCodeInfo_Location_descriptor_, &SourceCodeInfo_Location::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ GeneratedCodeInfo_descriptor_, &GeneratedCodeInfo::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ GeneratedCodeInfo_Annotation_descriptor_, &GeneratedCodeInfo_Annotation::default_instance());
}
} // namespace
@@ -626,6 +669,10 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto() {
delete SourceCodeInfo_reflection_;
delete SourceCodeInfo_Location::default_instance_;
delete SourceCodeInfo_Location_reflection_;
+ delete GeneratedCodeInfo::default_instance_;
+ delete GeneratedCodeInfo_reflection_;
+ delete GeneratedCodeInfo_Annotation::default_instance_;
+ delete GeneratedCodeInfo_Annotation_reflection_;
}
void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
@@ -699,7 +746,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.pr"
"otobuf.MethodOptions\022\037\n\020client_streaming"
"\030\005 \001(\010:\005false\022\037\n\020server_streaming\030\006 \001(\010:"
- "\005false\"\252\005\n\013FileOptions\022\024\n\014java_package\030\001"
+ "\005false\"\256\005\n\013FileOptions\022\024\n\014java_package\030\001"
" \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023ja"
"va_multiple_files\030\n \001(\010:\005false\022,\n\035java_g"
"enerate_equals_and_hash\030\024 \001(\010:\005false\022%\n\026"
@@ -711,56 +758,60 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"e\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031\n"
"\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enable_ar"
"enas\030\037 \001(\010:\005false\022\031\n\021objc_class_prefix\030$"
- " \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022\'\n\037javana"
- "no_use_deprecated_package\030& \001(\010\022C\n\024unint"
- "erpreted_option\030\347\007 \003(\0132$.google.protobuf"
- ".UninterpretedOption\":\n\014OptimizeMode\022\t\n\005"
- "SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003"
- "*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016MessageOptions\022&\n\027messag"
- "e_set_wire_format\030\001 \001(\010:\005false\022.\n\037no_sta"
- "ndard_descriptor_accessor\030\002 \001(\010:\005false\022\031"
- "\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tmap_entry\030\007"
- " \001(\010\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go"
- "ogle.protobuf.UninterpretedOption*\t\010\350\007\020\200"
- "\200\200\200\002\"\230\003\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#.g"
- "oogle.protobuf.FieldOptions.CType:\006STRIN"
- "G\022\016\n\006packed\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$.goog"
- "le.protobuf.FieldOptions.JSType:\tJS_NORM"
- "AL\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecated\030\003 "
- "\001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024unint"
- "erpreted_option\030\347\007 \003(\0132$.google.protobuf"
- ".UninterpretedOption\"/\n\005CType\022\n\n\006STRING\020"
- "\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002\"5\n\006JSType\022"
- "\r\n\tJS_NORMAL\020\000\022\r\n\tJS_STRING\020\001\022\r\n\tJS_NUMB"
- "ER\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023\n\013allow"
- "_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005false\022"
- "C\n\024uninterpreted_option\030\347\007 \003(\0132$.google."
- "protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\""
- "}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001 \001(\010:"
- "\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$."
- "google.protobuf.UninterpretedOption*\t\010\350\007"
- "\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndeprecated\030!"
- " \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003"
- "(\0132$.google.protobuf.UninterpretedOption"
- "*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndeprecat"
+ " \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022+\n\037javana"
+ "no_use_deprecated_package\030& \001(\010B\002\030\001\022C\n\024u"
+ "ninterpreted_option\030\347\007 \003(\0132$.google.prot"
+ "obuf.UninterpretedOption\":\n\014OptimizeMode"
+ "\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTI"
+ "ME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016MessageOptions\022&\n\027me"
+ "ssage_set_wire_format\030\001 \001(\010:\005false\022.\n\037no"
+ "_standard_descriptor_accessor\030\002 \001(\010:\005fal"
+ "se\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tmap_ent"
+ "ry\030\007 \001(\010\022C\n\024uninterpreted_option\030\347\007 \003(\0132"
+ "$.google.protobuf.UninterpretedOption*\t\010"
+ "\350\007\020\200\200\200\200\002\"\230\003\n\014FieldOptions\022:\n\005ctype\030\001 \001(\016"
+ "2#.google.protobuf.FieldOptions.CType:\006S"
+ "TRING\022\016\n\006packed\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$."
+ "google.protobuf.FieldOptions.JSType:\tJS_"
+ "NORMAL\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecate"
+ "d\030\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024u"
+ "ninterpreted_option\030\347\007 \003(\0132$.google.prot"
+ "obuf.UninterpretedOption\"/\n\005CType\022\n\n\006STR"
+ "ING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002\"5\n\006JST"
+ "ype\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS_STRING\020\001\022\r\n\tJS_"
+ "NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023\n\013a"
+ "llow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005fa"
+ "lse\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo"
+ "gle.protobuf.UninterpretedOption*\t\010\350\007\020\200\200"
+ "\200\200\002\"}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001 "
+ "\001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003("
+ "\0132$.google.protobuf.UninterpretedOption*"
+ "\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndeprecat"
"ed\030! \001(\010:\005false\022C\n\024uninterpreted_option\030"
"\347\007 \003(\0132$.google.protobuf.UninterpretedOp"
- "tion*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOption\022"
- ";\n\004name\030\002 \003(\0132-.google.protobuf.Uninterp"
- "retedOption.NamePart\022\030\n\020identifier_value"
- "\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022ne"
- "gative_int_value\030\005 \001(\003\022\024\n\014double_value\030\006"
- " \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggregate_"
- "value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part\030\001 \002"
- "(\t\022\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016SourceCodeI"
- "nfo\022:\n\010location\030\001 \003(\0132(.google.protobuf."
- "SourceCodeInfo.Location\032\206\001\n\010Location\022\020\n\004"
- "path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020lead"
- "ing_comments\030\003 \001(\t\022\031\n\021trailing_comments\030"
- "\004 \001(\t\022!\n\031leading_detached_comments\030\006 \003(\t"
- "BX\n\023com.google.protobufB\020DescriptorProto"
- "sH\001Z\ndescriptor\242\002\003GPB\252\002\032Google.Protobuf."
- "Reflection", 5010);
+ "tion*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndepr"
+ "ecated\030! \001(\010:\005false\022C\n\024uninterpreted_opt"
+ "ion\030\347\007 \003(\0132$.google.protobuf.Uninterpret"
+ "edOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOpt"
+ "ion\022;\n\004name\030\002 \003(\0132-.google.protobuf.Unin"
+ "terpretedOption.NamePart\022\030\n\020identifier_v"
+ "alue\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032"
+ "\n\022negative_int_value\030\005 \001(\003\022\024\n\014double_val"
+ "ue\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggreg"
+ "ate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part"
+ "\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016SourceC"
+ "odeInfo\022:\n\010location\030\001 \003(\0132(.google.proto"
+ "buf.SourceCodeInfo.Location\032\206\001\n\010Location"
+ "\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020"
+ "leading_comments\030\003 \001(\t\022\031\n\021trailing_comme"
+ "nts\030\004 \001(\t\022!\n\031leading_detached_comments\030\006"
+ " \003(\t\"\247\001\n\021GeneratedCodeInfo\022A\n\nannotation"
+ "\030\001 \003(\0132-.google.protobuf.GeneratedCodeIn"
+ "fo.Annotation\032O\n\nAnnotation\022\020\n\004path\030\001 \003("
+ "\005B\002\020\001\022\023\n\013source_file\030\002 \001(\t\022\r\n\005begin\030\003 \001("
+ "\005\022\013\n\003end\030\004 \001(\005BX\n\023com.google.protobufB\020D"
+ "escriptorProtosH\001Z\ndescriptor\242\002\003GPB\252\002\032Go"
+ "ogle.Protobuf.Reflection", 5184);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -785,6 +836,8 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
UninterpretedOption_NamePart::default_instance_ = new UninterpretedOption_NamePart();
SourceCodeInfo::default_instance_ = new SourceCodeInfo();
SourceCodeInfo_Location::default_instance_ = new SourceCodeInfo_Location();
+ GeneratedCodeInfo::default_instance_ = new GeneratedCodeInfo();
+ GeneratedCodeInfo_Annotation::default_instance_ = new GeneratedCodeInfo_Annotation();
FileDescriptorSet::default_instance_->InitAsDefaultInstance();
FileDescriptorProto::default_instance_->InitAsDefaultInstance();
DescriptorProto::default_instance_->InitAsDefaultInstance();
@@ -807,6 +860,8 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
UninterpretedOption_NamePart::default_instance_->InitAsDefaultInstance();
SourceCodeInfo::default_instance_->InitAsDefaultInstance();
SourceCodeInfo_Location::default_instance_->InitAsDefaultInstance();
+ GeneratedCodeInfo::default_instance_->InitAsDefaultInstance();
+ GeneratedCodeInfo_Annotation::default_instance_->InitAsDefaultInstance();
::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto);
}
@@ -8074,7 +8129,7 @@ bool FileOptions::MergePartialFromCodedStream(
break;
}
- // optional bool javanano_use_deprecated_package = 38;
+ // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
case 38: {
if (tag == 304) {
parse_javanano_use_deprecated_package:
@@ -8232,7 +8287,7 @@ void FileOptions::SerializeWithCachedSizes(
37, this->csharp_namespace(), output);
}
- // optional bool javanano_use_deprecated_package = 38;
+ // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
if (has_javanano_use_deprecated_package()) {
::google::protobuf::internal::WireFormatLite::WriteBool(38, this->javanano_use_deprecated_package(), output);
}
@@ -8358,7 +8413,7 @@ void FileOptions::SerializeWithCachedSizes(
37, this->csharp_namespace(), target);
}
- // optional bool javanano_use_deprecated_package = 38;
+ // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
if (has_javanano_use_deprecated_package()) {
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(38, this->javanano_use_deprecated_package(), target);
}
@@ -8469,7 +8524,7 @@ int FileOptions::ByteSize() const {
this->csharp_namespace());
}
- // optional bool javanano_use_deprecated_package = 38;
+ // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
if (has_javanano_use_deprecated_package()) {
total_size += 2 + 1;
}
@@ -9110,7 +9165,7 @@ void FileOptions::clear_csharp_namespace() {
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace)
}
-// optional bool javanano_use_deprecated_package = 38;
+// optional bool javanano_use_deprecated_package = 38 [deprecated = true];
bool FileOptions::has_javanano_use_deprecated_package() const {
return (_has_bits_[0] & 0x00004000u) != 0;
}
@@ -14057,6 +14112,812 @@ SourceCodeInfo::location() const {
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int GeneratedCodeInfo_Annotation::kPathFieldNumber;
+const int GeneratedCodeInfo_Annotation::kSourceFileFieldNumber;
+const int GeneratedCodeInfo_Annotation::kBeginFieldNumber;
+const int GeneratedCodeInfo_Annotation::kEndFieldNumber;
+#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.GeneratedCodeInfo.Annotation)
+}
+
+void GeneratedCodeInfo_Annotation::InitAsDefaultInstance() {
+}
+
+GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(const GeneratedCodeInfo_Annotation& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo.Annotation)
+}
+
+void GeneratedCodeInfo_Annotation::SharedCtor() {
+ ::google::protobuf::internal::GetEmptyString();
+ _cached_size_ = 0;
+ source_file_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ begin_ = 0;
+ end_ = 0;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+GeneratedCodeInfo_Annotation::~GeneratedCodeInfo_Annotation() {
+ // @@protoc_insertion_point(destructor:google.protobuf.GeneratedCodeInfo.Annotation)
+ SharedDtor();
+}
+
+void GeneratedCodeInfo_Annotation::SharedDtor() {
+ source_file_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (this != default_instance_) {
+ }
+}
+
+void GeneratedCodeInfo_Annotation::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* GeneratedCodeInfo_Annotation::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return GeneratedCodeInfo_Annotation_descriptor_;
+}
+
+const GeneratedCodeInfo_Annotation& GeneratedCodeInfo_Annotation::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ return *default_instance_;
+}
+
+GeneratedCodeInfo_Annotation* GeneratedCodeInfo_Annotation::default_instance_ = NULL;
+
+GeneratedCodeInfo_Annotation* GeneratedCodeInfo_Annotation::New(::google::protobuf::Arena* arena) const {
+ GeneratedCodeInfo_Annotation* n = new GeneratedCodeInfo_Annotation;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void GeneratedCodeInfo_Annotation::Clear() {
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<GeneratedCodeInfo_Annotation*>(16)->f)
+
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+ if (_has_bits_[0 / 32] & 14u) {
+ ZR_(begin_, end_);
+ if (has_source_file()) {
+ source_file_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ }
+
+#undef ZR_HELPER_
+#undef ZR_
+
+ path_.Clear();
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
+}
+
+bool GeneratedCodeInfo_Annotation::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.GeneratedCodeInfo.Annotation)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // repeated int32 path = 1 [packed = true];
+ case 1: {
+ if (tag == 10) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, this->mutable_path())));
+ } else if (tag == 8) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ 1, 10, input, this->mutable_path())));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(18)) goto parse_source_file;
+ break;
+ }
+
+ // optional string source_file = 2;
+ case 2: {
+ if (tag == 18) {
+ parse_source_file:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_source_file()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->source_file().data(), this->source_file().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.GeneratedCodeInfo.Annotation.source_file");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(24)) goto parse_begin;
+ break;
+ }
+
+ // optional int32 begin = 3;
+ case 3: {
+ if (tag == 24) {
+ parse_begin:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &begin_)));
+ set_has_begin();
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(32)) goto parse_end;
+ break;
+ }
+
+ // optional int32 end = 4;
+ case 4: {
+ if (tag == 32) {
+ parse_end:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &end_)));
+ set_has_end();
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormat::SkipField(
+ input, tag, mutable_unknown_fields()));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.GeneratedCodeInfo.Annotation)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.GeneratedCodeInfo.Annotation)
+ return false;
+#undef DO_
+}
+
+void GeneratedCodeInfo_Annotation::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.GeneratedCodeInfo.Annotation)
+ // repeated int32 path = 1 [packed = true];
+ if (this->path_size() > 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteTag(1, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
+ output->WriteVarint32(_path_cached_byte_size_);
+ }
+ for (int i = 0; i < this->path_size(); i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag(
+ this->path(i), output);
+ }
+
+ // optional string source_file = 2;
+ if (has_source_file()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->source_file().data(), this->source_file().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.GeneratedCodeInfo.Annotation.source_file");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 2, this->source_file(), output);
+ }
+
+ // optional int32 begin = 3;
+ if (has_begin()) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->begin(), output);
+ }
+
+ // optional int32 end = 4;
+ if (has_end()) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(4, this->end(), output);
+ }
+
+ if (_internal_metadata_.have_unknown_fields()) {
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
+ }
+ // @@protoc_insertion_point(serialize_end:google.protobuf.GeneratedCodeInfo.Annotation)
+}
+
+::google::protobuf::uint8* GeneratedCodeInfo_Annotation::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo.Annotation)
+ // repeated int32 path = 1 [packed = true];
+ if (this->path_size() > 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(
+ 1,
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+ target);
+ target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(
+ _path_cached_byte_size_, target);
+ }
+ for (int i = 0; i < this->path_size(); i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteInt32NoTagToArray(this->path(i), target);
+ }
+
+ // optional string source_file = 2;
+ if (has_source_file()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->source_file().data(), this->source_file().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.GeneratedCodeInfo.Annotation.source_file");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 2, this->source_file(), target);
+ }
+
+ // optional int32 begin = 3;
+ if (has_begin()) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->begin(), target);
+ }
+
+ // optional int32 end = 4;
+ if (has_end()) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(4, this->end(), target);
+ }
+
+ if (_internal_metadata_.have_unknown_fields()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.GeneratedCodeInfo.Annotation)
+ return target;
+}
+
+int GeneratedCodeInfo_Annotation::ByteSize() const {
+ int total_size = 0;
+
+ if (_has_bits_[1 / 32] & 14u) {
+ // optional string source_file = 2;
+ if (has_source_file()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->source_file());
+ }
+
+ // optional int32 begin = 3;
+ if (has_begin()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->begin());
+ }
+
+ // optional int32 end = 4;
+ if (has_end()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->end());
+ }
+
+ }
+ // repeated int32 path = 1 [packed = true];
+ {
+ int data_size = 0;
+ for (int i = 0; i < this->path_size(); i++) {
+ data_size += ::google::protobuf::internal::WireFormatLite::
+ Int32Size(this->path(i));
+ }
+ if (data_size > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);
+ }
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _path_cached_byte_size_ = data_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ total_size += data_size;
+ }
+
+ if (_internal_metadata_.have_unknown_fields()) {
+ total_size +=
+ ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+ unknown_fields());
+ }
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void GeneratedCodeInfo_Annotation::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const GeneratedCodeInfo_Annotation* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const GeneratedCodeInfo_Annotation>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void GeneratedCodeInfo_Annotation::MergeFrom(const GeneratedCodeInfo_Annotation& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ path_.MergeFrom(from.path_);
+ if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
+ if (from.has_source_file()) {
+ set_has_source_file();
+ source_file_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.source_file_);
+ }
+ if (from.has_begin()) {
+ set_begin(from.begin());
+ }
+ if (from.has_end()) {
+ set_end(from.end());
+ }
+ }
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
+}
+
+void GeneratedCodeInfo_Annotation::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void GeneratedCodeInfo_Annotation::CopyFrom(const GeneratedCodeInfo_Annotation& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool GeneratedCodeInfo_Annotation::IsInitialized() const {
+
+ return true;
+}
+
+void GeneratedCodeInfo_Annotation::Swap(GeneratedCodeInfo_Annotation* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void GeneratedCodeInfo_Annotation::InternalSwap(GeneratedCodeInfo_Annotation* other) {
+ path_.UnsafeArenaSwap(&other->path_);
+ source_file_.Swap(&other->source_file_);
+ std::swap(begin_, other->begin_);
+ std::swap(end_, other->end_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata GeneratedCodeInfo_Annotation::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = GeneratedCodeInfo_Annotation_descriptor_;
+ metadata.reflection = GeneratedCodeInfo_Annotation_reflection_;
+ return metadata;
+}
+
+
+// -------------------------------------------------------------------
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int GeneratedCodeInfo::kAnnotationFieldNumber;
+#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+GeneratedCodeInfo::GeneratedCodeInfo()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.GeneratedCodeInfo)
+}
+
+void GeneratedCodeInfo::InitAsDefaultInstance() {
+}
+
+GeneratedCodeInfo::GeneratedCodeInfo(const GeneratedCodeInfo& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo)
+}
+
+void GeneratedCodeInfo::SharedCtor() {
+ _cached_size_ = 0;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+GeneratedCodeInfo::~GeneratedCodeInfo() {
+ // @@protoc_insertion_point(destructor:google.protobuf.GeneratedCodeInfo)
+ SharedDtor();
+}
+
+void GeneratedCodeInfo::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void GeneratedCodeInfo::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* GeneratedCodeInfo::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return GeneratedCodeInfo_descriptor_;
+}
+
+const GeneratedCodeInfo& GeneratedCodeInfo::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ return *default_instance_;
+}
+
+GeneratedCodeInfo* GeneratedCodeInfo::default_instance_ = NULL;
+
+GeneratedCodeInfo* GeneratedCodeInfo::New(::google::protobuf::Arena* arena) const {
+ GeneratedCodeInfo* n = new GeneratedCodeInfo;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void GeneratedCodeInfo::Clear() {
+ annotation_.Clear();
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
+}
+
+bool GeneratedCodeInfo::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.GeneratedCodeInfo)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
+ case 1: {
+ if (tag == 10) {
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_annotation:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ input, add_annotation()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(10)) goto parse_loop_annotation;
+ input->UnsafeDecrementRecursionDepth();
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormat::SkipField(
+ input, tag, mutable_unknown_fields()));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.GeneratedCodeInfo)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.GeneratedCodeInfo)
+ return false;
+#undef DO_
+}
+
+void GeneratedCodeInfo::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.GeneratedCodeInfo)
+ // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
+ for (unsigned int i = 0, n = this->annotation_size(); i < n; i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 1, this->annotation(i), output);
+ }
+
+ if (_internal_metadata_.have_unknown_fields()) {
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
+ }
+ // @@protoc_insertion_point(serialize_end:google.protobuf.GeneratedCodeInfo)
+}
+
+::google::protobuf::uint8* GeneratedCodeInfo::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo)
+ // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
+ for (unsigned int i = 0, n = this->annotation_size(); i < n; i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 1, this->annotation(i), target);
+ }
+
+ if (_internal_metadata_.have_unknown_fields()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.GeneratedCodeInfo)
+ return target;
+}
+
+int GeneratedCodeInfo::ByteSize() const {
+ int total_size = 0;
+
+ // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
+ total_size += 1 * this->annotation_size();
+ for (int i = 0; i < this->annotation_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->annotation(i));
+ }
+
+ if (_internal_metadata_.have_unknown_fields()) {
+ total_size +=
+ ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+ unknown_fields());
+ }
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void GeneratedCodeInfo::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const GeneratedCodeInfo* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const GeneratedCodeInfo>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void GeneratedCodeInfo::MergeFrom(const GeneratedCodeInfo& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ annotation_.MergeFrom(from.annotation_);
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
+}
+
+void GeneratedCodeInfo::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void GeneratedCodeInfo::CopyFrom(const GeneratedCodeInfo& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool GeneratedCodeInfo::IsInitialized() const {
+
+ return true;
+}
+
+void GeneratedCodeInfo::Swap(GeneratedCodeInfo* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void GeneratedCodeInfo::InternalSwap(GeneratedCodeInfo* other) {
+ annotation_.UnsafeArenaSwap(&other->annotation_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata GeneratedCodeInfo::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = GeneratedCodeInfo_descriptor_;
+ metadata.reflection = GeneratedCodeInfo_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// GeneratedCodeInfo_Annotation
+
+// repeated int32 path = 1 [packed = true];
+int GeneratedCodeInfo_Annotation::path_size() const {
+ return path_.size();
+}
+void GeneratedCodeInfo_Annotation::clear_path() {
+ path_.Clear();
+}
+ ::google::protobuf::int32 GeneratedCodeInfo_Annotation::path(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.path)
+ return path_.Get(index);
+}
+ void GeneratedCodeInfo_Annotation::set_path(int index, ::google::protobuf::int32 value) {
+ path_.Set(index, value);
+ // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.path)
+}
+ void GeneratedCodeInfo_Annotation::add_path(::google::protobuf::int32 value) {
+ path_.Add(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.Annotation.path)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+GeneratedCodeInfo_Annotation::path() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.GeneratedCodeInfo.Annotation.path)
+ return path_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+GeneratedCodeInfo_Annotation::mutable_path() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.GeneratedCodeInfo.Annotation.path)
+ return &path_;
+}
+
+// optional string source_file = 2;
+bool GeneratedCodeInfo_Annotation::has_source_file() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void GeneratedCodeInfo_Annotation::set_has_source_file() {
+ _has_bits_[0] |= 0x00000002u;
+}
+void GeneratedCodeInfo_Annotation::clear_has_source_file() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+void GeneratedCodeInfo_Annotation::clear_source_file() {
+ source_file_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_source_file();
+}
+ const ::std::string& GeneratedCodeInfo_Annotation::source_file() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+ return source_file_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void GeneratedCodeInfo_Annotation::set_source_file(const ::std::string& value) {
+ set_has_source_file();
+ source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+}
+ void GeneratedCodeInfo_Annotation::set_source_file(const char* value) {
+ set_has_source_file();
+ source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+}
+ void GeneratedCodeInfo_Annotation::set_source_file(const char* value, size_t size) {
+ set_has_source_file();
+ source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+}
+ ::std::string* GeneratedCodeInfo_Annotation::mutable_source_file() {
+ set_has_source_file();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+ return source_file_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* GeneratedCodeInfo_Annotation::release_source_file() {
+ clear_has_source_file();
+ return source_file_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void GeneratedCodeInfo_Annotation::set_allocated_source_file(::std::string* source_file) {
+ if (source_file != NULL) {
+ set_has_source_file();
+ } else {
+ clear_has_source_file();
+ }
+ source_file_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), source_file);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+}
+
+// optional int32 begin = 3;
+bool GeneratedCodeInfo_Annotation::has_begin() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void GeneratedCodeInfo_Annotation::set_has_begin() {
+ _has_bits_[0] |= 0x00000004u;
+}
+void GeneratedCodeInfo_Annotation::clear_has_begin() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+void GeneratedCodeInfo_Annotation::clear_begin() {
+ begin_ = 0;
+ clear_has_begin();
+}
+ ::google::protobuf::int32 GeneratedCodeInfo_Annotation::begin() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.begin)
+ return begin_;
+}
+ void GeneratedCodeInfo_Annotation::set_begin(::google::protobuf::int32 value) {
+ set_has_begin();
+ begin_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.begin)
+}
+
+// optional int32 end = 4;
+bool GeneratedCodeInfo_Annotation::has_end() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void GeneratedCodeInfo_Annotation::set_has_end() {
+ _has_bits_[0] |= 0x00000008u;
+}
+void GeneratedCodeInfo_Annotation::clear_has_end() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+void GeneratedCodeInfo_Annotation::clear_end() {
+ end_ = 0;
+ clear_has_end();
+}
+ ::google::protobuf::int32 GeneratedCodeInfo_Annotation::end() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.end)
+ return end_;
+}
+ void GeneratedCodeInfo_Annotation::set_end(::google::protobuf::int32 value) {
+ set_has_end();
+ end_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.end)
+}
+
+// -------------------------------------------------------------------
+
+// GeneratedCodeInfo
+
+// repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
+int GeneratedCodeInfo::annotation_size() const {
+ return annotation_.size();
+}
+void GeneratedCodeInfo::clear_annotation() {
+ annotation_.Clear();
+}
+const ::google::protobuf::GeneratedCodeInfo_Annotation& GeneratedCodeInfo::annotation(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.annotation)
+ return annotation_.Get(index);
+}
+::google::protobuf::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::mutable_annotation(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.GeneratedCodeInfo.annotation)
+ return annotation_.Mutable(index);
+}
+::google::protobuf::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::add_annotation() {
+ // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.annotation)
+ return annotation_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >*
+GeneratedCodeInfo::mutable_annotation() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.GeneratedCodeInfo.annotation)
+ return &annotation_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >&
+GeneratedCodeInfo::annotation() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.GeneratedCodeInfo.annotation)
+ return annotation_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
// @@protoc_insertion_point(namespace_scope)
} // namespace protobuf
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 60255162..3fe07bf5 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -50,6 +50,8 @@ class FieldOptions;
class FileDescriptorProto;
class FileDescriptorSet;
class FileOptions;
+class GeneratedCodeInfo;
+class GeneratedCodeInfo_Annotation;
class MessageOptions;
class MethodDescriptorProto;
class MethodOptions;
@@ -2015,12 +2017,12 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
::std::string* release_csharp_namespace();
void set_allocated_csharp_namespace(::std::string* csharp_namespace);
- // optional bool javanano_use_deprecated_package = 38;
- bool has_javanano_use_deprecated_package() const;
- void clear_javanano_use_deprecated_package();
+ // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
+ bool has_javanano_use_deprecated_package() const PROTOBUF_DEPRECATED;
+ void clear_javanano_use_deprecated_package() PROTOBUF_DEPRECATED;
static const int kJavananoUseDeprecatedPackageFieldNumber = 38;
- bool javanano_use_deprecated_package() const;
- void set_javanano_use_deprecated_package(bool value);
+ bool javanano_use_deprecated_package() const PROTOBUF_DEPRECATED;
+ void set_javanano_use_deprecated_package(bool value) PROTOBUF_DEPRECATED;
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
int uninterpreted_option_size() const;
@@ -3390,6 +3392,228 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message {
void InitAsDefaultInstance();
static SourceCodeInfo* default_instance_;
};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT GeneratedCodeInfo_Annotation : public ::google::protobuf::Message {
+ public:
+ GeneratedCodeInfo_Annotation();
+ virtual ~GeneratedCodeInfo_Annotation();
+
+ GeneratedCodeInfo_Annotation(const GeneratedCodeInfo_Annotation& from);
+
+ inline GeneratedCodeInfo_Annotation& operator=(const GeneratedCodeInfo_Annotation& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+ return _internal_metadata_.unknown_fields();
+ }
+
+ inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+ return _internal_metadata_.mutable_unknown_fields();
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const GeneratedCodeInfo_Annotation& default_instance();
+
+ void Swap(GeneratedCodeInfo_Annotation* other);
+
+ // implements Message ----------------------------------------------
+
+ inline GeneratedCodeInfo_Annotation* New() const { return New(NULL); }
+
+ GeneratedCodeInfo_Annotation* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const GeneratedCodeInfo_Annotation& from);
+ void MergeFrom(const GeneratedCodeInfo_Annotation& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(GeneratedCodeInfo_Annotation* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // repeated int32 path = 1 [packed = true];
+ int path_size() const;
+ void clear_path();
+ static const int kPathFieldNumber = 1;
+ ::google::protobuf::int32 path(int index) const;
+ void set_path(int index, ::google::protobuf::int32 value);
+ void add_path(::google::protobuf::int32 value);
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+ path() const;
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+ mutable_path();
+
+ // optional string source_file = 2;
+ bool has_source_file() const;
+ void clear_source_file();
+ static const int kSourceFileFieldNumber = 2;
+ const ::std::string& source_file() const;
+ void set_source_file(const ::std::string& value);
+ void set_source_file(const char* value);
+ void set_source_file(const char* value, size_t size);
+ ::std::string* mutable_source_file();
+ ::std::string* release_source_file();
+ void set_allocated_source_file(::std::string* source_file);
+
+ // optional int32 begin = 3;
+ bool has_begin() const;
+ void clear_begin();
+ static const int kBeginFieldNumber = 3;
+ ::google::protobuf::int32 begin() const;
+ void set_begin(::google::protobuf::int32 value);
+
+ // optional int32 end = 4;
+ bool has_end() const;
+ void clear_end();
+ static const int kEndFieldNumber = 4;
+ ::google::protobuf::int32 end() const;
+ void set_end(::google::protobuf::int32 value);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo.Annotation)
+ private:
+ inline void set_has_source_file();
+ inline void clear_has_source_file();
+ inline void set_has_begin();
+ inline void clear_has_begin();
+ inline void set_has_end();
+ inline void clear_has_end();
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ ::google::protobuf::uint32 _has_bits_[1];
+ mutable int _cached_size_;
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 > path_;
+ mutable int _path_cached_byte_size_;
+ ::google::protobuf::internal::ArenaStringPtr source_file_;
+ ::google::protobuf::int32 begin_;
+ ::google::protobuf::int32 end_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+ void InitAsDefaultInstance();
+ static GeneratedCodeInfo_Annotation* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT GeneratedCodeInfo : public ::google::protobuf::Message {
+ public:
+ GeneratedCodeInfo();
+ virtual ~GeneratedCodeInfo();
+
+ GeneratedCodeInfo(const GeneratedCodeInfo& from);
+
+ inline GeneratedCodeInfo& operator=(const GeneratedCodeInfo& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+ return _internal_metadata_.unknown_fields();
+ }
+
+ inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+ return _internal_metadata_.mutable_unknown_fields();
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const GeneratedCodeInfo& default_instance();
+
+ void Swap(GeneratedCodeInfo* other);
+
+ // implements Message ----------------------------------------------
+
+ inline GeneratedCodeInfo* New() const { return New(NULL); }
+
+ GeneratedCodeInfo* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const GeneratedCodeInfo& from);
+ void MergeFrom(const GeneratedCodeInfo& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(GeneratedCodeInfo* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ typedef GeneratedCodeInfo_Annotation Annotation;
+
+ // accessors -------------------------------------------------------
+
+ // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
+ int annotation_size() const;
+ void clear_annotation();
+ static const int kAnnotationFieldNumber = 1;
+ const ::google::protobuf::GeneratedCodeInfo_Annotation& annotation(int index) const;
+ ::google::protobuf::GeneratedCodeInfo_Annotation* mutable_annotation(int index);
+ ::google::protobuf::GeneratedCodeInfo_Annotation* add_annotation();
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >*
+ mutable_annotation();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >&
+ annotation() const;
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ ::google::protobuf::uint32 _has_bits_[1];
+ mutable int _cached_size_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation > annotation_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+ void InitAsDefaultInstance();
+ static GeneratedCodeInfo* default_instance_;
+};
// ===================================================================
@@ -5970,7 +6194,7 @@ inline void FileOptions::set_allocated_csharp_namespace(::std::string* csharp_na
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace)
}
-// optional bool javanano_use_deprecated_package = 38;
+// optional bool javanano_use_deprecated_package = 38 [deprecated = true];
inline bool FileOptions::has_javanano_use_deprecated_package() const {
return (_has_bits_[0] & 0x00004000u) != 0;
}
@@ -7194,6 +7418,175 @@ SourceCodeInfo::location() const {
return location_;
}
+// -------------------------------------------------------------------
+
+// GeneratedCodeInfo_Annotation
+
+// repeated int32 path = 1 [packed = true];
+inline int GeneratedCodeInfo_Annotation::path_size() const {
+ return path_.size();
+}
+inline void GeneratedCodeInfo_Annotation::clear_path() {
+ path_.Clear();
+}
+inline ::google::protobuf::int32 GeneratedCodeInfo_Annotation::path(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.path)
+ return path_.Get(index);
+}
+inline void GeneratedCodeInfo_Annotation::set_path(int index, ::google::protobuf::int32 value) {
+ path_.Set(index, value);
+ // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.path)
+}
+inline void GeneratedCodeInfo_Annotation::add_path(::google::protobuf::int32 value) {
+ path_.Add(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.Annotation.path)
+}
+inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+GeneratedCodeInfo_Annotation::path() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.GeneratedCodeInfo.Annotation.path)
+ return path_;
+}
+inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+GeneratedCodeInfo_Annotation::mutable_path() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.GeneratedCodeInfo.Annotation.path)
+ return &path_;
+}
+
+// optional string source_file = 2;
+inline bool GeneratedCodeInfo_Annotation::has_source_file() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void GeneratedCodeInfo_Annotation::set_has_source_file() {
+ _has_bits_[0] |= 0x00000002u;
+}
+inline void GeneratedCodeInfo_Annotation::clear_has_source_file() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+inline void GeneratedCodeInfo_Annotation::clear_source_file() {
+ source_file_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_source_file();
+}
+inline const ::std::string& GeneratedCodeInfo_Annotation::source_file() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+ return source_file_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void GeneratedCodeInfo_Annotation::set_source_file(const ::std::string& value) {
+ set_has_source_file();
+ source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+}
+inline void GeneratedCodeInfo_Annotation::set_source_file(const char* value) {
+ set_has_source_file();
+ source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+}
+inline void GeneratedCodeInfo_Annotation::set_source_file(const char* value, size_t size) {
+ set_has_source_file();
+ source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+}
+inline ::std::string* GeneratedCodeInfo_Annotation::mutable_source_file() {
+ set_has_source_file();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+ return source_file_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* GeneratedCodeInfo_Annotation::release_source_file() {
+ clear_has_source_file();
+ return source_file_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void GeneratedCodeInfo_Annotation::set_allocated_source_file(::std::string* source_file) {
+ if (source_file != NULL) {
+ set_has_source_file();
+ } else {
+ clear_has_source_file();
+ }
+ source_file_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), source_file);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
+}
+
+// optional int32 begin = 3;
+inline bool GeneratedCodeInfo_Annotation::has_begin() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void GeneratedCodeInfo_Annotation::set_has_begin() {
+ _has_bits_[0] |= 0x00000004u;
+}
+inline void GeneratedCodeInfo_Annotation::clear_has_begin() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+inline void GeneratedCodeInfo_Annotation::clear_begin() {
+ begin_ = 0;
+ clear_has_begin();
+}
+inline ::google::protobuf::int32 GeneratedCodeInfo_Annotation::begin() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.begin)
+ return begin_;
+}
+inline void GeneratedCodeInfo_Annotation::set_begin(::google::protobuf::int32 value) {
+ set_has_begin();
+ begin_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.begin)
+}
+
+// optional int32 end = 4;
+inline bool GeneratedCodeInfo_Annotation::has_end() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void GeneratedCodeInfo_Annotation::set_has_end() {
+ _has_bits_[0] |= 0x00000008u;
+}
+inline void GeneratedCodeInfo_Annotation::clear_has_end() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+inline void GeneratedCodeInfo_Annotation::clear_end() {
+ end_ = 0;
+ clear_has_end();
+}
+inline ::google::protobuf::int32 GeneratedCodeInfo_Annotation::end() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.end)
+ return end_;
+}
+inline void GeneratedCodeInfo_Annotation::set_end(::google::protobuf::int32 value) {
+ set_has_end();
+ end_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.end)
+}
+
+// -------------------------------------------------------------------
+
+// GeneratedCodeInfo
+
+// repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
+inline int GeneratedCodeInfo::annotation_size() const {
+ return annotation_.size();
+}
+inline void GeneratedCodeInfo::clear_annotation() {
+ annotation_.Clear();
+}
+inline const ::google::protobuf::GeneratedCodeInfo_Annotation& GeneratedCodeInfo::annotation(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.annotation)
+ return annotation_.Get(index);
+}
+inline ::google::protobuf::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::mutable_annotation(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.GeneratedCodeInfo.annotation)
+ return annotation_.Mutable(index);
+}
+inline ::google::protobuf::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::add_annotation() {
+ // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.annotation)
+ return annotation_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >*
+GeneratedCodeInfo::mutable_annotation() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.GeneratedCodeInfo.annotation)
+ return &annotation_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >&
+GeneratedCodeInfo::annotation() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.GeneratedCodeInfo.annotation)
+ return annotation_;
+}
+
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
// -------------------------------------------------------------------
@@ -7237,6 +7630,10 @@ SourceCodeInfo::location() const {
// -------------------------------------------------------------------
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
// @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index c59a6022..3e664d59 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -379,7 +379,7 @@ message FileOptions {
// Whether the nano proto compiler should generate in the deprecated non-nano
// suffixed package.
- optional bool javanano_use_deprecated_package = 38;
+ optional bool javanano_use_deprecated_package = 38 [deprecated = true];
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
@@ -777,3 +777,29 @@ message SourceCodeInfo {
repeated string leading_detached_comments = 6;
}
}
+
+// Describes the relationship between generated code and its original source
+// file. A GeneratedCodeInfo message is associated with only one generated
+// source file, but may contain references to different source .proto files.
+message GeneratedCodeInfo {
+ // An Annotation connects some span of text in generated code to an element
+ // of its generating .proto file.
+ repeated Annotation annotation = 1;
+ message Annotation {
+ // Identifies the element in the original source .proto file. This field
+ // is formatted the same as SourceCodeInfo.Location.path.
+ repeated int32 path = 1 [packed=true];
+
+ // Identifies the filesystem path to the original source .proto.
+ optional string source_file = 2;
+
+ // Identifies the starting offset in bytes in the generated code
+ // that relates to the identified object.
+ optional int32 begin = 3;
+
+ // Identifies the ending offset in bytes in the generated code that
+ // relates to the identified offset. The end offset should be one past
+ // the last relevant byte (so the length of the text = end - begin).
+ optional int32 end = 4;
+ }
+}
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 432236ce..61f3f558 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -692,7 +692,7 @@ class LIBPROTOBUF_EXPORT StringTypeHandlerBase {
class StringTypeHandler : public StringTypeHandlerBase {
public:
static int SpaceUsed(const string& value) {
- return sizeof(value) + StringSpaceUsedExcludingSelf(value);
+ return static_cast<int>(sizeof(value)) + StringSpaceUsedExcludingSelf(value);
}
};
diff --git a/src/google/protobuf/stubs/atomicops.h b/src/google/protobuf/stubs/atomicops.h
index 31e2b782..cb93227f 100644
--- a/src/google/protobuf/stubs/atomicops.h
+++ b/src/google/protobuf/stubs/atomicops.h
@@ -76,7 +76,7 @@ typedef int32 Atomic32;
#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT
// We need to be able to go between Atomic64 and AtomicWord implicitly. This
// means Atomic64 and AtomicWord should be the same type on 64-bit.
-#if defined(__ILP32__) || defined(GOOGLE_PROTOBUF_OS_NACL) || defined(GOOGLE_PROTOBUF_ARCH_SPARC)
+#if defined(__ILP32__) || defined(GOOGLE_PROTOBUF_OS_NACL)
// NaCl's intptr_t is not actually 64-bits on 64-bit!
// http://code.google.com/p/nativeclient/issues/detail?id=1162
// sparcv9's pointer type is 32bits
diff --git a/src/google/protobuf/stubs/platform_macros.h b/src/google/protobuf/stubs/platform_macros.h
index 5cde8f4e..22b35723 100644
--- a/src/google/protobuf/stubs/platform_macros.h
+++ b/src/google/protobuf/stubs/platform_macros.h
@@ -65,7 +65,7 @@
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
#elif defined(sparc)
#define GOOGLE_PROTOBUF_ARCH_SPARC 1
-#ifdef SOLARIS_64BIT_ENABLED
+#if defined(__sparc_v9__) || defined(__sparcv9) || defined(__arch64__)
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
#else
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
diff --git a/src/google/protobuf/stubs/statusor.h b/src/google/protobuf/stubs/statusor.h
index a9d2b374..ad848701 100644
--- a/src/google/protobuf/stubs/statusor.h
+++ b/src/google/protobuf/stubs/statusor.h
@@ -224,14 +224,14 @@ inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<T>& other) {
template<typename T>
template<typename U>
inline StatusOr<T>::StatusOr(const StatusOr<U>& other)
- : status_(other.status_), value_(other.value_) {
+ : status_(other.status_), value_(other.status_.ok() ? other.value_ : NULL) {
}
template<typename T>
template<typename U>
inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<U>& other) {
status_ = other.status_;
- value_ = other.value_;
+ if (status_.ok()) value_ = other.value_;
return *this;
}
diff --git a/src/google/protobuf/unittest_well_known_types.proto b/src/google/protobuf/unittest_well_known_types.proto
index 2cb7775c..c9075244 100644
--- a/src/google/protobuf/unittest_well_known_types.proto
+++ b/src/google/protobuf/unittest_well_known_types.proto
@@ -39,6 +39,8 @@ message TestWellKnownTypes {
google.protobuf.BoolValue bool_field = 16;
google.protobuf.StringValue string_field = 17;
google.protobuf.BytesValue bytes_field = 18;
+ // Part of struct, but useful to be able to test separately
+ google.protobuf.Value value_field = 19;
}
// A repeated field for each well-known type.
diff --git a/src/google/protobuf/util/internal/testdata/maps.proto b/src/google/protobuf/util/internal/testdata/maps.proto
index 7fb42a26..6475ecdd 100644
--- a/src/google/protobuf/util/internal/testdata/maps.proto
+++ b/src/google/protobuf/util/internal/testdata/maps.proto
@@ -44,6 +44,35 @@ message MapOut {
map<string, MapM> map1 = 1;
map<string, MapOut> map2 = 2;
map<int32, string> map3 = 3;
+ map<bool, string> map4 = 5;
+ string bar = 4;
+}
+
+// A message with exactly the same wire representation as MapOut, but using
+// repeated message fields instead of map fields. We use this message to test
+// the wire-format compatibility of the JSON transcoder (e.g., whether it
+// handles missing keys correctly).
+message MapOutWireFormat {
+ message Map1Entry {
+ string key = 1;
+ MapM value = 2;
+ }
+ repeated Map1Entry map1 = 1;
+ message Map2Entry {
+ string key = 1;
+ MapOut value = 2;
+ }
+ repeated Map2Entry map2 = 2;
+ message Map3Entry {
+ int32 key = 1;
+ string value = 2;
+ }
+ repeated Map3Entry map3 = 3;
+ message Map4Entry {
+ bool key = 1;
+ string value = 2;
+ }
+ repeated Map4Entry map4 = 5;
string bar = 4;
}